if(!reminderfox) var reminderfox={};
if(!reminderfox.network) reminderfox.network={};

// constants
const REMINDER_FOX_MIGRATED_PREF_VERSION="1.9.9.3.1";

//const REMINDER_FOX_WELCOME_PAGE_URL = "http://reminderfox.mozdev.org/welcome.html";
const REMINDER_FOX_WELCOME_UPDATE_PAGE_URL = "http://www.reminderfox.org/update";

const REMINDER_FOX_PAGE_URL = "http://www.reminderfox.org";
const REMINDER_FOX_WELCOME_PAGE_URL = "http://www.reminderfox.org/welcome-to-reminderfox";
//const REMINDER_FOX_WELCOME_UPDATE_PAGE_URL = "http://www.reminderfox.org/update";
const REMINDER_PRIORITY_NORMAL = null;  // default
const REMINDER_PRIORITY_IMPORTANT = 1;

const REMINDER_RECURRENCE_ONETIME = null;  // default
const REMINDER_RECURRENCE_YEARLY = 0;
const REMINDER_RECURRENCE_MONTHLY_DATE = 1;
const REMINDER_RECURRENCE_MONTHLY_DAY = 3;
const REMINDER_RECURRENCE_WEEKLY = 4;
const REMINDER_RECURRENCE_YEARLY_DAY = 6;
const REMINDER_RECURRENCE_DAILY = 7;

const REMINDERFOX_REMIND_UNTIL_COMPLETE_NONE = null;  // default
const REMINDERFOX_REMIND_UNTIL_COMPLETE_TO_BE_MARKED = 1;
const REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED = 2;

const REMINDERFOX_EXTENDED = "X-REMINDERFOX-";

const REMINDERFOX_FILE_LAST_MODIFIED=REMINDERFOX_EXTENDED + "LAST-MODIFIED";

const REMINDER_FOX_DOMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];// # of days in Non-Leap year Month 
const REMINDER_FOX_lDOMonth = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // # of days in Leap year Month 

// configurable preferences   
const REMINDER_FOX_ENABLE_ALERT_PREF = "enableAlertFor"; 
const REMINDER_FOX_ENABLE_ALERT_PREF_NONE = "none"; 
const REMINDER_FOX_ENABLE_ALERT_PREF_TODAY = "today"; 
const REMINDER_FOX_ENABLE_ALERT_PREF_UPCOMING = "upcoming"; 
const REMINDER_FOX_ENABLE_ALERT_PREF_ALL = "all"; 
const REMINDER_FOX_SUSPEND_ALERT_PREF = "SUSPENDED:";

const REMINDER_FOX_ENABLE_CONTEXT_MENUS = "enableContextMenus";
const REMINDER_FOX_HIDE_FOX_PAW = "hideThatRidiculousFox";
const REMINDER_FOX_SHOW_SIDEBAR = "defaults.showSidebar";
const REMINDER_FOX_SHOW_FILTERS = "defaults.showFilters";
const REMINDER_FOX_DEFAULTS_ALARM_SNOOZE_TIME = "defaults.alarm.snooze.time";
const REMINDER_FOX_DEFAULTS_ALARM_SNOOZE_UNITS = "defaults.alarm.snooze.units";
const REMINDER_FOX_DEFAULTS_ALARM_SNOOZE_ACTION = "defaults.alarm.snooze.action";

const REMINDER_FOX_MAIL_PATH = "mail.app.location";
const REMINDER_FOX_MAIL_SENDER = "mail.sender";

const REMINDER_FOX_ALERT_TIMEOUT_PREF="alertTimeout";
const REMINDER_FOX_ALERT_TIMEOUT_DEFAULT = 120; // number of minutes between alerts

const REMINDER_FOX_HTML_STYLESHEET_PREF = "html.stylesheet";

const REMINDER_FOX_SHOW_WEEK_NUMS_PREF = "showWeekNumbers";

const REMINDER_FOX_UPCOMING_REMINDER_DAYS_PREF="upcomingReminderDays";
const REMINDER_FOX_UPCOMING_REMINDER_DAYS_DEFAULT = 15;

const REMINDER_FOX_UPCOMING_REMINDERS_LABEL="upcomingRemindersLabel";
const REMINDER_FOX_UPCOMING_REMINDERS_LABEL_DEFAULT="[longMonth] [date]: [reminderDesc] ([time])";

const REMINDER_FOX_TODAYS_REMINDERS_LABEL="todaysRemindersLabel";
const REMINDER_FOX_TODAYS_REMINDERS_LABEL_DEFAULT="[reminderDesc] ([time])";

const REMINDER_FOX_LIST_DATE_LABEL="listDateLabel";
const REMINDER_FOX_LIST_DATE_LABEL_DEFAULT = "[longMonth] [date]";

const REMINDER_FOX_SHOW_STATUS_TEXT="showReminderStatusText";
const REMINDER_FOX_SHOW_STATUS_TEXT_DEFAULT=true;

const REMINDER_FOX_SHOW_REMINDERS_IN_TOOLTIP="showRemindersInTooltip";
const REMINDER_FOX_SHOW_REMINDERS_IN_TOOLTIP_DEFAULT=true;

const REMINDER_FOX_SHOW_TODOS_IN_TOOLTIP="showTodosInTooltip";
const REMINDER_FOX_SHOW_TODOS_IN_TOOLTIP_DEFAULT=true;

const REMINDER_FOX_ALARM_SOUND="alarmSound";
const REMINDER_FOX_ALARM_SOUND_DEFAULT=true;

const REMINDER_FOX_ALERT_SOUND="alertSound";
const REMINDER_FOX_ALERT_SOUND_DEFAULT=false;

const REMINDER_FOX_ALARM_SOUND_PATH="alarmSoundPath";
const REMINDER_FOX_ALARM_SOUND_PATH__DEFAULT="";

const REMINDER_FOX_USE_24_HOUR_TIME="use24HourTime";
const REMINDER_FOX_USE_24_HOUR_TIME_DEFAULT=false;

const REMINDER_FOX_ALARMS_ENABLED="alarmsEnabled";
const REMINDER_FOX_ALARMS_ENABLED_DEFAULT=true;

const REMINDER_FOX_HIGHLIGHT_TODAYS_REMINDERS="highlightTodaysReminders";
const REMINDER_FOX_HIGHLIGHT_TODAYS_REMINDERS_DEFAULT=true;


const REMINDER_FOX_DEFAULT_REPEAT="reminderDefaultRepeat";
const REMINDER_FOX_DEFAULT_ALARM_TIME="reminderDefaultAlarmTime";
const REMINDER_FOX_DEFAULT_ALARM_UNITS="reminderDefaultAlarmUnits";
const REMINDER_FOX_DEFAULT_REMIND_UNTIL_COMPLETED="reminderDefaultRemindUntilCompleted";
const REMINDER_FOX_DEFAULT_ALL_DAY="reminderDefaultAllDay";
const REMINDER_FOX_DEFAULT_CATEGORY="reminderDefaultCategory";
const REMINDER_FOX_DEFAULT_SHOW_IN_TOOLTIP="reminderDefaultShowInTooltip";
const REMINDER_FOX_DEFAULT_FILTER_REMINDER="reminderDefaultFilter";
const REMINDER_FOX_DEFAULT_FILTER_TODO="reminderDefaultFilterTodo";
const REMINDER_FOX_DEFAULT_MORE="reminderDefaultMore";
const REMINDER_FOX_DEFAULT_MORE_DEFAULT_VALUE="location,url";
const REMINDER_FOX_CALENDAR_START_DAY="calendarStartDay";
const REMINDER_FOX_CALENDAR_START_DAY_DEFAULT= 0;
const REMINDER_FOX_CALENDAR_SIZE="calendarSize";
const REMINDER_FOX_ALARM_SOUND_INTERVAL="alarmSoundInterval";
const REMINDER_FOX_STATUS_TEXT_MAX_LENGTH ="statusTextMaxLength";

const REMINDER_FOX_ALARMS_SHOW_IN_TABS ="alarms.showInTabs";

const REMINDER_FOX_KEY_SHORTCUT_OPEN ="keyboard.shortcut.openReminderFox";
const REMINDER_FOX_KEY_SHORTCUT_ADD ="keyboard.shortcut.addEvent";

const REMINDER_FOX_TOOLBAR="toolbar";
const REMINDER_FOX_TOOLBAR_DEFAULT="status-bar";

const REMINDER_FOX_DEFAULT_EDIT="defaultEdit";
const REMINDER_FOX_DEFAULT_EDIT_DEFAULT="reminders";

const REMINDER_FOX_TOOLBAR_POSITION = "toolbarPosition";
const REMINDER_FOX_TOOLBAR_POSITION_DEFAULT = -1;

const REMINDER_FOX_REPEAT_PREVIOUS_OCCURRENCES = "repeatPreviousOccurrences";
const REMINDER_FOX_REPEAT_UPCOMING_OCCURRENCES = "repeatUpcomingOccurrences";

const REMINDER_FOX_HIDE_COMPLETED_ITEMS = "hideCompletedItems";

const REMINDER_FOX_PREF_ALERTSLIDER_MAX_HEIGHT = "alertSliderMaxHeight";
const REMINDER_FOX_PREF_ALERTSLIDER_OPEN_TIME = "alertOpenTime";



const REMINDER_FOX_MIGRATED_PREF="migrated";
const REMINDER_FOX_SHOW_WELCOME_PAGE="showWelcomePage";

const REMINDER_FOX_TODO_LISTS = "todoLists";

const REMINDER_FOX_SUBSCRIPTIONS = "subscriptions";

const REMINDER_FOX_SORT_COLUMNS_PREF = "sortColumns";

const REMINDER_FOX_PREF = "extensions.reminderFox";

const REMINDER_FOX_DEFAULT_TODOS_CATEGORY = "ToDo's";
const REMINDER_FOX_DEFAULT_REMINDERS_CATEGORY = "Reminders";

const REMINDER_FOX_QUICK_ALARMS = "quickAlarms"; 


// network
const REMINDER_FOX_NETWORK_SYNCHRONIZE = "network.synchronize";
const REMINDER_FOX_NETWORK_SYNCHRONIZE_DEFAULT = false;
const REMINDER_FOX_PROTO = "network.protocol";
const REMINDER_FOX_DEFAULT_PROTO = "ftp";
const REMINDER_FOX_ADDRESS = "network.address";
const REMINDER_FOX_USERNAME = "network.username";

const REMINDER_FOX_UI_MODE_HEADLESS_SHOW_ALL_UI = 0;
const REMINDER_FOX_UI_MODE_HEADLESS = 1;
const REMINDER_FOX_UI_MODE_HEADLESS_SHOW_ERRORS = 2;

// categories
const REMINDER_FOX_CATEGORIES = "categories";  

// old reminder/todo strings for migration purposes
const REMINDER_FOX_REMINDERS = "reminderFox.reminders";
const REMINDER_FOX_TODOS = "reminderFox.todos";

const REMINDER_FOX_STORE_FILE =  "storeFile";

const REMINDER_FOX_DEBUG = "debug";
const REMINDER_FOX_LOG = REMINDER_FOX_DEBUG + "." + "loglevel";
const REMINDER_FOX_LOG_FILE = REMINDER_FOX_DEBUG + "." + "file";
const REMINDER_FOX_LOG_LEVEL_NONE = 0;
const REMINDER_FOX_LOG_LEVEL_INFO = 1;
const REMINDER_FOX_LOG_LEVEL_FINE = 2;
const REMINDER_FOX_LOG_LEVEL_SUPER_FINE = 3;
const REMINDER_FOX_LOG_LEVEL_DEBUG = 4;
const REMINDER_FOX_LOG_DEFAULT =REMINDER_FOX_LOG_LEVEL_NONE;
const REMINDER_FOX_LAST_UPDATE =  "lastUpdate";
const REMINDER_FOX_LAST_ALERT = "lastAlert";
const REMINDER_FOX_LAST_PROCESSED = "lastProcessed";
const REMINDER_FOX_LAST_MODIFIED = "lastModified";

// images
const REMINDER_FOX_NOTES_IMAGE =  "chrome://reminderfox/skin/images/notes.png";
const REMINDER_FOX_MAIL_IMAGE =  "chrome://reminderfox/skin/images/mail.png";
const REMINDER_FOX_REMIND_UNTIL_COMPLETED_TO_BE_MARKED_IMAGE = "chrome://reminderfox/skin/images/ribbon-blue-small.png";
const REMINDER_FOX_REMIND_UNTIL_COMPLETED_IMAGE = "chrome://reminderfox/skin/images/ribbon-red-small.png";
const REMINDER_FOX_COMPLETED_IMAGE = "chrome://global/skin/checkbox/cbox-check.gif";
const REMINDER_FOX_COMPLETED_TODO_IMAGE = "chrome://global/skin/checkbox/cbox-check.gif";
const REMINDER_FOX_SHOW_IN_TOOLTIP_IMAGE = "chrome://reminderfox/skin/images/tooltip.png";
const REMINDER_FOX_ALARM_IMAGE = "chrome://reminderfox/skin/images/alarmbell.png";
const REMINDER_FOX_ALARM_SNOOZE_IMAGE = "chrome://reminderfox/skin/images/alarmbellSnooze.png";
	
// sorting order	
const REMINDER_FOX_SORT_DIRECTION_ASCENDING = 0;
const REMINDER_FOX_SORT_DIRECTION_DESCENDING = 1;
	
// The number of milliseconds in one day
const REMINDER_FOX_ONE_DAY = 1000 * 60 * 60 * 24;
const REMINDER_FOX_NEGATIVE_ONE_DAY = REMINDER_FOX_ONE_DAY * -1;
const REMINDER_FOX_TWO_DAYS = REMINDER_FOX_ONE_DAY * 2;

const reminderFox_prefs = Components.classes["@mozilla.org/preferences-service;1"].
                getService(Components.interfaces.nsIPrefBranch);
                
const reminderFox_prefsBranch = Components.classes["@mozilla.org/preferences-service;1"]. 
				getService(Components.interfaces.nsIPrefService). 
				getBranch(REMINDER_FOX_PREF + ".");
				
				              
const reminderFox_nsISupportsString = Components.interfaces.nsISupportsString;
const reminderFox_consoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);


const go4Process = Components.classes["@mozilla.org/process/util;1"]
	                        .createInstance(Components.interfaces.nsIProcess);        

const externalAppLauncher = Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
                            .getService(Components.interfaces.nsPIExternalAppLauncher);

const reminderFox_weekday=new Array("SU", "MO", "TU", "WE", "TH", "FR", "SA" );

var reminderFox_lastModifiedTime;

var reminderFox_timezones = { };

var reminderFoxEvents;
var reminderFoxTodosArray;   // ToDo's, Movies, Albums
var reminderFoxExtraInfo;
var reminderFoxExtraInfoPrefix;

var reminderfox_Method;

var global_reminderFoxBundle;

var gRmFx_LastEvent = null;

const REMINDERFOX_PREF_TYPE = { BOOL : 0, INT : 1, CHAR : 2, COMPLEX : 3 }

var  reminderFox_user_prefs = null;
function reminderFox_initUserPrefsArray() {
	reminderFox_user_prefs = { } ;
	
	reminderFox_user_prefs[REMINDER_FOX_ENABLE_ALERT_PREF] = REMINDERFOX_PREF_TYPE.CHAR;
	reminderFox_user_prefs[REMINDER_FOX_SHOW_STATUS_TEXT] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_USE_24_HOUR_TIME] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_HIGHLIGHT_TODAYS_REMINDERS] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_HIDE_COMPLETED_ITEMS] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_SHOW_REMINDERS_IN_TOOLTIP] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_SHOW_TODOS_IN_TOOLTIP] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_ENABLE_CONTEXT_MENUS] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_HIDE_FOX_PAW] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_UPCOMING_REMINDER_DAYS_PREF] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULT_EDIT] = REMINDERFOX_PREF_TYPE.CHAR;
	reminderFox_user_prefs[REMINDER_FOX_ALERT_TIMEOUT_PREF] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_UPCOMING_REMINDERS_LABEL] = REMINDERFOX_PREF_TYPE.COMPLEX;
	reminderFox_user_prefs[REMINDER_FOX_TODAYS_REMINDERS_LABEL] = REMINDERFOX_PREF_TYPE.COMPLEX;
	reminderFox_user_prefs[REMINDER_FOX_LIST_DATE_LABEL] = REMINDERFOX_PREF_TYPE.COMPLEX;
	reminderFox_user_prefs[REMINDER_FOX_ALARM_SOUND] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_ALERT_SOUND] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_CALENDAR_START_DAY] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_SHOW_WEEK_NUMS_PREF] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_CALENDAR_SIZE] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_ALARM_SOUND_INTERVAL] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_STATUS_TEXT_MAX_LENGTH] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULTS_ALARM_SNOOZE_TIME] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULTS_ALARM_SNOOZE_UNITS] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULTS_ALARM_SNOOZE_ACTION] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_STORE_FILE] = REMINDERFOX_PREF_TYPE.CHAR;
	reminderFox_user_prefs[REMINDER_FOX_NETWORK_SYNCHRONIZE] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_ALARMS_SHOW_IN_TABS] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_SHOW_SIDEBAR] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_SHOW_FILTERS] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_SHOW_WEEK_NUMS_PREF] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_REPEAT_UPCOMING_OCCURRENCES] = REMINDERFOX_PREF_TYPE.INT;		
	reminderFox_user_prefs[REMINDER_FOX_REPEAT_PREVIOUS_OCCURRENCES] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_PREF_ALERTSLIDER_MAX_HEIGHT] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_PREF_ALERTSLIDER_OPEN_TIME] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_ALARM_SOUND_PATH] = REMINDERFOX_PREF_TYPE.CHAR;
	reminderFox_user_prefs[REMINDER_FOX_KEY_SHORTCUT_OPEN] = REMINDERFOX_PREF_TYPE.CHAR;
	reminderFox_user_prefs[REMINDER_FOX_KEY_SHORTCUT_ADD] = REMINDERFOX_PREF_TYPE.CHAR;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULT_ALL_DAY] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULT_REPEAT] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULT_MORE] = REMINDERFOX_PREF_TYPE.CHAR;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULT_ALARM_TIME] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULT_ALARM_UNITS] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULT_REMIND_UNTIL_COMPLETED] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_PROTO] = REMINDERFOX_PREF_TYPE.CHAR;
	reminderFox_user_prefs[REMINDER_FOX_ADDRESS] = REMINDERFOX_PREF_TYPE.CHAR;
	reminderFox_user_prefs[REMINDER_FOX_USERNAME] = REMINDERFOX_PREF_TYPE.CHAR;
	reminderFox_user_prefs[REMINDER_FOX_HTML_STYLESHEET_PREF] = REMINDERFOX_PREF_TYPE.CHAR;
	reminderFox_user_prefs[REMINDER_FOX_TODO_LISTS] = REMINDERFOX_PREF_TYPE.COMPLEX;
	reminderFox_user_prefs[REMINDER_FOX_SUBSCRIPTIONS] = REMINDERFOX_PREF_TYPE.COMPLEX;
	reminderFox_user_prefs[REMINDER_FOX_CATEGORIES] = REMINDERFOX_PREF_TYPE.COMPLEX;
	reminderFox_user_prefs[REMINDER_FOX_TOOLBAR_POSITION] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_TOOLBAR] = REMINDERFOX_PREF_TYPE.CHAR;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULT_SHOW_IN_TOOLTIP] = REMINDERFOX_PREF_TYPE.BOOL;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULT_FILTER_REMINDER] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULT_FILTER_TODO] = REMINDERFOX_PREF_TYPE.INT;
	reminderFox_user_prefs[REMINDER_FOX_DEFAULT_CATEGORY] = REMINDERFOX_PREF_TYPE.COMPLEX;		
	reminderFox_user_prefs[REMINDER_FOX_SORT_COLUMNS_PREF] = REMINDERFOX_PREF_TYPE.COMPLEX;		
}

function reminderFox_getPreferenceValue( preferenceName, defaultValue ) {
	if ( reminderFox_user_prefs == null ) {
		reminderFox_initUserPrefsArray();
	}
	var prefValue = null;
	try { 
		var prefType = reminderFox_user_prefs[preferenceName];
		if ( prefType == REMINDERFOX_PREF_TYPE.COMPLEX ) {			
			prefValue = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + preferenceName);	
		}
		else if ( prefType == REMINDERFOX_PREF_TYPE.CHAR ) {
				prefValue = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + preferenceName );				
		}
		else if ( prefType == REMINDERFOX_PREF_TYPE.BOOL ) {
				prefValue = reminderFox_prefs.getBoolPref(REMINDER_FOX_PREF + "." + preferenceName );
		}
		else if ( prefType == REMINDERFOX_PREF_TYPE.INT ) {
				prefValue = reminderFox_prefs.getIntPref(REMINDER_FOX_PREF + "." + preferenceName );
		}		
	}
	catch ( e ) {
		prefValue = defaultValue;  // if no existing value, use the default value		
	}
	if (prefValue == null)  prefValue =  defaultValue;  //gW_prefs 2009-06-04 
	return prefValue;
}

function reminderFox_setPreferenceValue( preferenceName, preferenceValue ) {	
	if ( reminderFox_user_prefs == null ) {
		reminderFox_initUserPrefsArray();
	}
	try { 
		var prefType = reminderFox_user_prefs[preferenceName];
		if ( prefType == REMINDERFOX_PREF_TYPE.COMPLEX ) {				
			reminderFox_setUnicodePref( preferenceName, preferenceValue);			 				
		}
		else if ( prefType == REMINDERFOX_PREF_TYPE.CHAR ) {					
			reminderFox_prefsBranch.setCharPref( preferenceName, preferenceValue);					
		}
		else if ( prefType == REMINDERFOX_PREF_TYPE.BOOL ) {
			if ( preferenceValue == "true" || preferenceValue == true ) {
				reminderFox_prefsBranch.setBoolPref( preferenceName, true);	
			}
			else {
				reminderFox_prefsBranch.setBoolPref( preferenceName, false);	
			}			
		}
		else if ( prefType == REMINDERFOX_PREF_TYPE.INT ) {
				reminderFox_prefsBranch.setIntPref(  preferenceName, parseInt( preferenceValue) );				
		}	
	}
	catch ( e ) {		
		reminderFox_logMessageLevel("exception setting VAL: " +REMINDER_FOX_PREF + "." + preferenceName + " == " + preferenceValue + "  :" + 
			 new Date() + " -- " + lastModified, REMINDER_FOX_LOG_LEVEL_INFO);	 
	}
};


function 	rmReadCategories2prefs() {
	var rmCategoriesStandard = null;

		try {
			rmCategoriesStandard = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + REMINDER_FOX_CATEGORIES);	
		} catch(e) {
			rmCategoriesStandard = "";
		}
		if (rmCategoriesStandard == "") {
			rmWriteCategories2prefs(rmCategoriesStandard);   /* write back eg. to initialize with default values  */
		}
	return rmCategoriesStandard;
}

function rmWriteCategories2prefs(rmCategoriesStandard) {	
		reminderFox_setUnicodePref( REMINDER_FOX_CATEGORIES, rmCategoriesStandard);			
}


function reminderFox_getBundle() {
	if ( global_reminderFoxBundle == null ) {
		global_reminderFoxBundle = document.getElementById("reminderFox-bundle");  
	}
	return global_reminderFoxBundle;
}

function reminderFox_logMessageLevel(logString, level){
	var logLevel = reminderFox_prefs.getIntPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_LOG);
	if ( level <= logLevel  ) {
	    if(reminderFox_consoleService) {
	      reminderFox_consoleService.logStringMessage("reminderFox: " + logString);
	      if ( logLevel >= 2 ) {
	      	dump( "reminderFox: " + logString + "\n"  );
	      }
	    }
  	}
  	
  	// if the user has specified a log file, then write out log messages to file
  	var logFile = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_LOG_FILE);
  	if ( logFile != null && logFile.length > 0 ) {
  		
  		// uncomment this if you want to only output DEBUG messages only; useful if sending a direct
  		// xpi to a user filled with specific DEBUG-level statements
  		// dump: nls - this should be commented out for final release
  		//if ( level != REMINDER_FOX_LOG_LEVEL_DEBUG ) {
  		//	return; 
  		//} 
  		
  		// if the user has set to DEBUG; only output debug lines to file
  		if ( logLevel == REMINDER_FOX_LOG_LEVEL_DEBUG && level != logLevel ) {
  			return;
  		}
  		
  		// log it to file
  		try { 
			var file = Components.classes["@mozilla.org/file/local;1"]
						.createInstance(Components.interfaces.nsILocalFile);
			file.initWithPath( logFile );
		
			if (file ) { 
				if ( !file.exists() ) {
					file.create( Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 420 );
				}  
				reminderFox_appendStringToFile("LogLevel " + level + ": " + logString + "\n-----\n", file, true);
			}
  		}
  		catch( e ) {
	  		if(reminderFox_consoleService) {
		      reminderFox_consoleService.logStringMessage("ReminderFox: Failed writing debug file: " +
	  				 e.name + ": " + e.description + ": " + e.fileName + ": " + e.lineNumber + ": " + e.message  + "\n" +  e.stack);
		      dump( "ReminderFox: Failed writing debug file: " +
	  				 e.name + ": " + e.description + ": " + e.fileName + ": "  + e.lineNumber + ": " + e.message  + "\n" +  e.stack);
		    }
  		}
	}
}

function reminderFox_debug_printStack() {
	var errno = errno;
     var fileName = Components.stack.caller.filename;
     var lineNumber = Components.stack.caller.lineNumber;
     var functionName = Components.stack.caller.name;
    
     
	 var frame = Components.stack.caller;
   var str = "";
   while (frame) {
   	 var name = frame.functionName ? frame.functionName : "[anonymous]";
   	
     if (frame.filename)
       str += frame.filename + ", Line " + frame.lineNumber;
     else
       str += "[" + gConsoleBundle.getString("noFile") + "]";
     
     str += " --> ";
     
     if (frame.functionName)
       str += frame.functionName;
     else
       str += "[" + gConsoleBundle.getString("noFunction") + "]";
       
     str += "\n";
     
     frame = frame.caller;
   }     
   
   dump( str + "\n");
     
}

/*
 *  function getStackTrace () {
      var frame = Components.stack.caller;
     var str = "<top>";
 
     while (frame)
     {
         var name = frame.name ? frame.name : "[anonymous]";
         str += "\n" + name + "@" + frame.lineNumber;
         frame = frame.caller;
     }
     return str; 
 }
 */
 
/* get unicode string value from preference store */
function reminderFox_getUnicodePref(prefName) {
    return reminderFox_prefs.getComplexValue(prefName, reminderFox_nsISupportsString).data;
}

/* set unicode string value */
function reminderFox_setUnicodePref(prefName,prefValue) {
    var sString = Components.classes["@mozilla.org/supports-string;1"].createInstance(reminderFox_nsISupportsString);
    sString.data = prefValue;
    reminderFox_prefsBranch.setComplexValue(prefName,reminderFox_nsISupportsString,sString);
}

// Object representing reminder events
function ReminderFoxEvent( reminderId, reminderDate, reminderSummary ) {
	this.id = reminderId;
    this.date = reminderDate;    // date object for reminder (using current year)
    this.endDate = null;
    this.durationTime = null;
    this.summary = reminderSummary;  // text of reminder
    this.notes = null;
    this.recurrence =     { type: null, endDate: null, interval: null, byDay: null }       // byday = "MO,TU,WE..."
    this.priority = null;
    this.remindUntilCompleted = null;
    this.allDayEvent = true;
    this.alarm = null;
    this.alarmLastAcknowledge = null;
    this.lastModified = null;    
    this.completedDate = null;
    this.messageID = null;
    this.extraInfo = null;
    this.categories = null;
    this.snoozeTime = null;
    this.url = null;
    this.location = null;
}

// Object representing ToDos
function ReminderFoxTodo( todoId, todoSummary, todoDate ) {
	this.id = todoId;
    this.summary = todoSummary;
    this.date = todoDate;    // date object for reminder (using current year)
    this.endDate = null;
    this.durationTime = null;
    this.priority = null;;
    this.dateStamp = null;
    this.notes = null;   
    this.recurrence =     { type: null, endDate: null, interval: null, byDay: null }  
    this.categories = null;
    this.allDayEvent = true;
    this.showInTooltip = false;
    this.completedDate = null;
    this.messageID = null;
    this.alarm = null;
    this.alarmLastAcknowledge = null;    
    this.extraInfo = null;
    this.snoozeTime = null;
    this.url = null;
    this.location = null;
}

function ReminderFoxQuickAlarm( qa_text, qa_notes, qa_alarmTime, qa_snoozeTime ) {
	this.text = qa_text;
	this.alarmTime = qa_alarmTime;
	this.snoozeTime = qa_snoozeTime;
	this.notes  = qa_notes;
}


// convenience function for dump debug; comment out
//function dd( str ) {
//	dump( str + "\n" );  
//}

/*
 * make a clone object of an event - useful if you want to temporarily modify some properties of an event, 
 * but don't want to change the actual model 
 */
function reminderFox_cloneReminderFoxEvent( reminderFoxEvent ) {
	var newDate = new Date( reminderFoxEvent.date.getTime() );
	var newReminderFoxEvent = new ReminderFoxEvent( reminderFoxEvent.id, newDate, reminderFoxEvent.summary );
	newReminderFoxEvent.notes = reminderFoxEvent.notes;
	newReminderFoxEvent.recurrence =  { type:  reminderFoxEvent.recurrence.type, endDate:  reminderFoxEvent.recurrence.endDate, interval:  reminderFoxEvent.recurrence.interval, byDay:  reminderFoxEvent.recurrence.byDay } ;
	newReminderFoxEvent.priority = reminderFoxEvent.priority;
	newReminderFoxEvent.remindUntilCompleted = reminderFoxEvent.remindUntilCompleted;
	newReminderFoxEvent.completedDate = reminderFoxEvent.completedDate;	
	newReminderFoxEvent.categories = reminderFoxEvent.categories;
	newReminderFoxEvent.allDayEvent = reminderFoxEvent.allDayEvent;
	newReminderFoxEvent.alarm = reminderFoxEvent.alarm;
    newReminderFoxEvent.alarmLastAcknowledge = reminderFoxEvent.alarmLastAcknowledge;
    newReminderFoxEvent.messageID = reminderFoxEvent.messageID;
    newReminderFoxEvent.lastModified = reminderFoxEvent.lastModified;
    newReminderFoxEvent.extraInfo = reminderFoxEvent.extraInfo;
    newReminderFoxEvent.snoozeTime = reminderFoxEvent.snoozeTime;
    newReminderFoxEvent.location = reminderFoxEvent.location;
    newReminderFoxEvent.url = reminderFoxEvent.url;
    if ( reminderFoxEvent.endDate != null ) {
    	newReminderFoxEvent.endDate = new Date( reminderFoxEvent.endDate.getTime() );
    }
    newReminderFoxEvent.durationTime = reminderFoxEvent.durationTime;
	return newReminderFoxEvent;
}	



/*
 * make a clone object of an event - useful if you want to temporarily modify some properties of an event, 
 * but don't want to change the actual model 
 */
function reminderFox_cloneReminderFoxTodo( reminderFoxTodo ) {
	var newDate;
	if ( reminderFoxTodo.date != null ) {
		 newDate = new Date( reminderFoxTodo.date.getTime() );
	}
	var newReminderFoxTodo = new ReminderFoxTodo(  reminderFoxTodo.id, reminderFoxTodo.summary, newDate );
	newReminderFoxTodo.priority = reminderFoxTodo.priority;
	newReminderFoxTodo.showInTooltip = reminderFoxTodo.showInTooltip;
	newReminderFoxTodo.notes = reminderFoxTodo.notes;
	newReminderFoxTodo.completedDate = reminderFoxTodo.completedDate;
	newReminderFoxTodo.messageID = reminderFoxTodo.messageID;
	newReminderFoxTodo.allDayEvent = reminderFoxTodo.allDayEvent;
	newReminderFoxTodo.recurrence =  { type:  reminderFoxTodo.recurrence.type, endDate:  reminderFoxTodo.recurrence.endDate, interval:  reminderFoxTodo.recurrence.interval, byDay:  reminderFoxTodo.recurrence.byDay } ;
	newReminderFoxTodo.categories = reminderFoxTodo.categories;
	newReminderFoxTodo.alarm = reminderFoxTodo.alarm;
    newReminderFoxTodo.alarmLastAcknowledge = reminderFoxTodo.alarmLastAcknowledge;	
    newReminderFoxTodo.extraInfo = reminderFoxTodo.extraInfo;	
    newReminderFoxTodo.snoozeTime = reminderFoxTodo.snoozeTime;
    newReminderFoxTodo.location = reminderFoxTodo.location;
    newReminderFoxTodo.url = reminderFoxTodo.url;
    if ( reminderFoxTodo.endDate != null ) {
    	newReminderFoxTodo.endDate =new Date( reminderFoxTodo.endDate.getTime() );
    }
    newReminderFoxTodo.durationTime = reminderFoxTodo.durationTime;
	return newReminderFoxTodo;
}	

function reminderFox_isLeapYear(year) { 
	return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) ? true : false;
}


function reminderFox_launchHelp() {
    var faqURL = reminderFox_getBundle().getString("rf.faqURL");
    reminderFox_openURL( faqURL );
}

function reminderFox_openURL(UrlToGoTo) {
	/*
	// fails with non-full URLs (eg: "google.com")
	var ioService = Components.classes["@mozilla.org/network/io-service;1"]
                              .getService(Components.interfaces.nsIIOService);
	var uri = ioService.newURI(UrlToGoTo, null, null);

	// now pass this uri to the operating system
	var extProtocolSvc =
       Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
                 .getService(Components.interfaces.nsIExternalProtocolService);
	if (extProtocolSvc)
   	extProtocolSvc.loadUrl(uri);
   	
   return;
	*/
   //   if( reminderFox_isThunderBird() ) {   ** replaced with next line  	
	if("@mozilla.org/messenger;1" in Components.classes) {
        var messenger = Components.classes["@mozilla.org/messenger;1"].createInstance()
                                  .QueryInterface(Components.interfaces.nsIMessenger);
                                  
        messenger.launchExternalURL(UrlToGoTo);
    } else {        
        var navWindow;
        
        // Try to get the most recently used browser window
        try {
            var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
                               .getService(Components.interfaces.nsIWindowMediator);
            navWindow = wm.getMostRecentWindow("navigator:browser");
        } catch(ex) {}
        
        if (navWindow) {  // Open the URL in most recently used browser window
            if ("delayedOpenTab" in navWindow) {
                navWindow.delayedOpenTab(UrlToGoTo);
            } else if ("loadURI" in navWindow) {
                navWindow.loadURI(UrlToGoTo);
            } else {
                navWindow._content.location.href = UrlToGoTo;
            }
        } else {  // If there is no recently used browser window open new browser window with the URL
            var ass = Components.classes["@mozilla.org/appshell/appShellService;1"]
                                .getService(Components.interfaces.nsIAppShellService);
            var win = ass.hiddenDOMWindow;
            
            win.openDialog("chrome://navigator/content/navigator.xul", "",
                           "chrome,all, dialog=no", UrlToGoTo );
        }
    }	
 /*
    var uri = Components.classes["@mozilla.org/network/standard-url;1"].createInstance(Components.interfaces.nsIURI);
    uri.spec = aURL;
    var protocolSvc = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"].getService(Components.interfaces.nsIExternalProtocolService);
    protocolSvc.loadUrl(uri);
    */
}

function reminderFox_isMailEvent( event ) {
	return event.messageID != null || reminderFox_isGMailEvent(event);
}

function reminderFox_isGMailEvent( event ) {
	return event.url != null && ( 
		//event.url.indexOf( "/mail/?shva" ) != -1;
		event.url.indexOf( "mail.google" ) != -1 ||
		event.url.indexOf( "mail.live" ) != -1 ||
		event.url.indexOf( ".mail." ) != -1 );  // handle windows live, etc
}

function reminderFox_focusBrowser() {
	if("@mozilla.org/messenger;1" in Components.classes) {
   } else {
        var navWindow;
        
        // Try to get the most recently used browser window
        try {
            var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
                               .getService(Components.interfaces.nsIWindowMediator);
            navWindow = wm.getMostRecentWindow("navigator:browser");
        } catch(ex) {}
        
        if (navWindow) {  // Open the URL in most recently used browser window
        	navWindow.focus();
        } else {  // If there is no recently used browser window open new browser window with the URL
            var ass = Components.classes["@mozilla.org/appshell/appShellService;1"]
                                .getService(Components.interfaces.nsIAppShellService);
            var win = ass.hiddenDOMWindow;
            win.focus();
        }
    }	
 /*
    var uri = Components.classes["@mozilla.org/network/standard-url;1"].createInstance(Components.interfaces.nsIURI);
    uri.spec = aURL;
    var protocolSvc = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"].getService(Components.interfaces.nsIExternalProtocolService);
    protocolSvc.loadUrl(uri);
    */
}



/*
Firefox
{ec8030f7-c20a-464f-9b0e-13a3a9e97384}

Thunderbird
{3550f703-e582-4d05-9a08-453d09bdfdc6}

Nvu
{136c295a-4a5a-41cf-bf24-5cee526720d5}

Mozilla Suite
{86c18b42-e466-45a9-ae7a-9b95ba6f5640}

SeaMonkey
{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}

Sunbird
{718e30fb-e89b-41dd-9da7-e25a45638b28}

Netscape Browser
{3db10fab-e461-4c80-8b97-957ad5f8ea47}

Flock Browser
{a463f10c-3994-11da-9945-000d60ca027b}	
*/
const REMINDERFOX_SEAMONKEY_ID = "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}";
const REMINDERFOX_THUNDERBIRD_ID = "{3550f703-e582-4d05-9a08-453d09bdfdc6}";
const REMINDERFOX_POSTBOX_ID = "postbox@postbox-inc.com";

function reminderFox_appId () {
	var aID;
	if("@mozilla.org/xre/app-info;1" in Components.classes) {
	    // running under Mozilla 1.8 or later
	    aID = Components.classes["@mozilla.org/xre/app-info;1"]
	                   .getService(Components.interfaces.nsIXULAppInfo).ID;
	} else {
   	try {
   		aID = Components.classes["@mozilla.org/preferences-service;1"]
                     .getService(Components.interfaces.nsIPrefBranch)
                     .getCharPref("app.id");
   	} catch(e) {}
	}
	return aID;
}


function rmFx_isMessenger() {
	var id = reminderFox_appId();
	if ( id != null && (id == REMINDERFOX_THUNDERBIRD_ID) || (id == REMINDERFOX_POSTBOX_ID)) {
		return true;
	} else { 
		return false;
	}
}


function reminderFox_isSunbirdOrLightning() {
	var id = reminderFox_appId();

	// check if this is Sunbird
 	if ( id != null && id == "{718e30fb-e89b-41dd-9da7-e25a45638b28}" ) {
		return true;
	}
	else 	if ( id != null && id == REMINDERFOX_THUNDERBIRD_ID ) {
		var em = Components.classes["@mozilla.org/extensions/manager;1"]
                   .getService(Components.interfaces.nsIExtensionManager);
		var addon = em.getItemForID("{e2fda1a4-762b-4020-b5ad-a41df1933103}");
		// check to see if the version attribute exists (if not, then the addon doesn't exist)
		if ( addon != null && (addon.version != null && addon.version != "" )) {
			return true;
		}		
	}
	return false;
}

/*
 * @deprecated - can't rely on this, as the translated month values may differ between the properties and dtd files
 *
function reminderFox_getMonthAsInteger(monthTextValue) {
	var prefMonth;
	switch (monthTextValue.toUpperCase()) {
		
		case reminderFox_getBundle().getString("rf.options.month.0.name").toUpperCase():
			prefMonth = 0;
			break;

		case reminderFox_getBundle().getString("rf.options.month.1.name").toUpperCase():
			prefMonth = 1;
			break;

		case reminderFox_getBundle().getString("rf.options.month.2.name").toUpperCase():
			prefMonth = 2;
			break;

		case reminderFox_getBundle().getString("rf.options.month.3.name").toUpperCase():
			prefMonth = 3;
			break;

		case reminderFox_getBundle().getString("rf.options.month.4.name").toUpperCase():
			prefMonth = 4;
			break;

		case reminderFox_getBundle().getString("rf.options.month.5.name").toUpperCase():
			prefMonth = 5;
			break;

		case reminderFox_getBundle().getString("rf.options.month.6.name").toUpperCase():
			prefMonth = 6;
			break;

		case reminderFox_getBundle().getString("rf.options.month.7.name").toUpperCase():
			prefMonth = 7;
			break;

		case reminderFox_getBundle().getString("rf.options.month.8.name").toUpperCase():
			prefMonth = 8;
			break;

		case reminderFox_getBundle().getString("rf.options.month.9.name").toUpperCase():
			prefMonth = 9;
			break;

		case reminderFox_getBundle().getString("rf.options.month.10.name").toUpperCase():
			prefMonth = 10;
			break;

		case reminderFox_getBundle().getString("rf.options.month.11.name").toUpperCase():
			prefMonth = 11;
			break;
					
	}
	return prefMonth;

}


function reminderFox_getShortMonthAsInteger(monthTextValue) {
	var prefMonth;
	switch (monthTextValue.toUpperCase()) {
		case reminderFox_getBundle().getString("rf.options.month.0.Mmm").toUpperCase():
			prefMonth = 0;
			break;

		case reminderFox_getBundle().getString("rf.options.month.1.Mmm").toUpperCase():
			prefMonth = 1;
			break;

		case reminderFox_getBundle().getString("rf.options.month.2.Mmm").toUpperCase():
			prefMonth = 2;
			break;

		case reminderFox_getBundle().getString("rf.options.month.3.Mmm").toUpperCase():
			prefMonth = 3;
			break;

		case reminderFox_getBundle().getString("rf.options.month.4.Mmm").toUpperCase():
			prefMonth = 4;
			break;

		case reminderFox_getBundle().getString("rf.options.month.5.Mmm").toUpperCase():
			prefMonth = 5;
			break;

		case reminderFox_getBundle().getString("rf.options.month.6.Mmm").toUpperCase():
			prefMonth = 6;
			break;

		case reminderFox_getBundle().getString("rf.options.month.7.Mmm").toUpperCase():
			prefMonth = 7;
			break;

		case reminderFox_getBundle().getString("rf.options.month.8.Mmm").toUpperCase():
			prefMonth = 8;
			break;

		case reminderFox_getBundle().getString("rf.options.month.9.Mmm").toUpperCase():
			prefMonth = 9;
			break;

		case reminderFox_getBundle().getString("rf.options.month.10.Mmm").toUpperCase():
			prefMonth = 10;
			break;

		case reminderFox_getBundle().getString("rf.options.month.11.Mmm").toUpperCase():
			prefMonth = 11;
			break;
					
	}
	return prefMonth;

}
*/

function reminderFox_networkSynchronizeCallback() {
	reminderFox_upload_Startup_headless(REMINDER_FOX_UI_MODE_HEADLESS_SHOW_ERRORS);	
}

function reminderFox_getMonthAsText(integerValue) {
	return reminderFox_getBundle().getString("rf.options.month."+integerValue+".name");
}

function reminderFox_launchWelcomePage(isNew) { 
	try {
		function welcome(version, isNew) {
			try {
				var browser = top.getBrowser();
				var pageURL = REMINDER_FOX_WELCOME_PAGE_URL;
				if ( !isNew && version != null ) {
					pageURL = REMINDER_FOX_WELCOME_UPDATE_PAGE_URL;
				}
				browser.selectedTab=browser.addTab(pageURL + "?version=" + version);
			} catch(e) {
			}
		}
		var showWelcomePage = reminderFox_prefs.getBoolPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_SHOW_WELCOME_PAGE );
		if ( showWelcomePage ) {
			setTimeout(welcome,100,REMINDER_FOX_MIGRATED_PREF_VERSION, isNew);
		}
	} catch(e) {
	}

}

function reminderFox_loadDefaultPreferences() {
	try { 
		var oldVersionNumber = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_MIGRATED_PREF); 
		if ( oldVersionNumber != REMINDER_FOX_MIGRATED_PREF_VERSION ) {
			if ( oldVersionNumber == null || oldVersionNumber == "" ) {
				// this pref is not set; this is new installation...  
				// handle any new work here
                reminderFox_firstStart();
				reminderFox_launchWelcomePage(true);	
			}
			else {
				reminderFox_launchWelcomePage(false);	
				
				reminderFox_handleMigration( oldVersionNumber );	
			}
			// set version number to new current version
			try {
				reminderFox_prefsBranch.setCharPref(REMINDER_FOX_MIGRATED_PREF, REMINDER_FOX_MIGRATED_PREF_VERSION);		
			} catch(e) {		
			}	
			// this is an older version; we need to handle migration code	
			//	reminderFox_handleMigration( oldVersionNumber );				
		}		
	} catch(e) {
		// this is an older version; we need to handle migration code		
		reminderFox_handleMigration("0.0");
	}				
	
	//	Firefox 4 disables the addon-bar (status-bar) by default, meaning that new users will have 
	// a poor first experience.  So on first install/update on FF4, let's just make sure the 
	// addon-bar is shown
	var addonBar = document.getElementById("addon-bar");
	if (addonBar) {
		if (addonBar.collapsed) {
			 var reminderFox_toolbar = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_TOOLBAR);
			 // if the pref is set to addonbar or status bar we should show this
			 if (reminderFox_toolbar != null &&
			 	(reminderFox_toolbar == "addon-bar" || reminderFox_toolbar == "status-bar")) {
			 	setToolbarVisibility(addonBar, true);
			 }
		}
	}

	try {
		reminderFox_prefs.getIntPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_TOOLBAR_POSITION);
	} catch(e) {
		reminderFox_prefsBranch.setIntPref(REMINDER_FOX_TOOLBAR_POSITION, REMINDER_FOX_TOOLBAR_POSITION_DEFAULT);
		
		try {
			// set the default location to the current location as of this moment
		    var reminderFox_toolbar = document.getElementById(reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_TOOLBAR));
		    var box = document.getElementById("reminderFox-statusLabel");
		    if (reminderFox_toolbar) {
		    	var currentIndex = reminderFox_indexOf(reminderFox_toolbar, box, true);
		    	reminderFox_prefsBranch.setIntPref(REMINDER_FOX_TOOLBAR_POSITION, currentIndex);	    	
		    }
		}
		catch (e) {
		}
	}	

	try {
		// clear out last alert time - because we always want to show the alert slider at least once on startup
		reminderFox_prefsBranch.setCharPref( REMINDER_FOX_LAST_ALERT, "");	
	} catch(e) {		
	}		
	
	try {
		reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_LAST_MODIFIED);
	} catch(e) {
		reminderFox_prefsBranch.setCharPref(REMINDER_FOX_LAST_MODIFIED, 	"");
	}
	
	// set default categories if none are present
	var categories = "";
	try {
		categories = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + REMINDER_FOX_CATEGORIES);		
	} catch(e) {		
		categories = "";
	}
	if ( categories == "" ) {
		var defaultCategories =  reminderFox_getBundle().getString("rf.categories.initial.defaults");		
		reminderFox_setUnicodePref( REMINDER_FOX_CATEGORIES, defaultCategories);		
	}
	
	// clear out debug file if it's there (just overwrite with a new header)
  	var logFile = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_LOG_FILE);
  	if ( logFile != null && logFile.length > 0 ) {
  		// log it to file
		var file = Components.classes["@mozilla.org/file/local;1"]
					.createInstance(Components.interfaces.nsILocalFile);
		file.initWithPath( logFile );
		
		if (file ) { 
			reminderFox_writeStringToFile("ReminderFox " + REMINDER_FOX_MIGRATED_PREF_VERSION +"\n" +
				rmFxCore.infoXR() + "\n\n", file, true);
		}
	}
	
		
//	try {
//		// clear out last process  time - because we always want to process  on startup
//		reminderFox_prefsBranch.setCharPref( REMINDER_FOX_LAST_PROCESSED, "");	
//	} catch(e) {		
//	}
}



/**
 *   'Default Views' -- Set and Info
 */
function rmFx_migrate_defaultView  (mode) {
//gW_DefaultViews
// extensions.reminderFox.views backup Mail/Send=<SUMMARY:Mail,Send;DATE:-1Y,3M;>,lastYear=<DATE:-1Y;>,
   if ('Info' == mode) { // 
      //alert ("Info about 'Default View' set -- how to handle etc .. ");
      return;
   }

   if ('Set' == mode) { // read the 'views.default' set and add 'view's on it 
   // to the 'views' set; for checking use name only, 
   // don't change any exsisting 'view' definition

    var views = null;
      try { // read 'views'
          views = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + "views");
       } catch (ex) {}

      var defaultViews = "";
      var i=0;
      try {
         while (reminderFox_getBundle().getString("rf.views.default.label." + i) != null) {
            defaultViews +=  reminderFox_getBundle().getString("rf.views.default.label." + i)
                 + "=<" + reminderFox_getBundle().getString("rf.views.default.value." + i) + ">,";
            i++;         
         }
      } catch(ex) {}

      if ((views == null) || (views =="")) {
           views = defaultViews;
      } else {
	      var cViews = views;	   
	      var defViewsArray = defaultViews.split(";>,");
	      var defCount = defViewsArray.length;
	
		   if (defCount > 0){
		      while ( defCount -- ) {
		         var defLabel = defViewsArray[defCount].split("=<")[0];
		         var defValue = defViewsArray[defCount].split("=<")[1];
		
		         var isView = true;       
				 if ( cViews.length > 0 ) { 
			         var cViewsArray = cViews.split(";>,");
			         var cCount = cViewsArray.length;
			         while ( cCount -- ) {
			            var cLabel = cViewsArray[cCount].split("=<")[0];  // ex: FoxInfo=<DATE:TODAY;>,
			            if ((defLabel == "") || (cLabel == defLabel)) {         
			                isView = false;
			            }
			         }   
					}     
		         if ((isView) && (defLabel != "")) {
		            views += defLabel + "=<" + defValue + ";>,"
		         }            
		      } // while ( dCount -- )
		   }
	   }     
	   reminderFox_setUnicodePref("views", views);
	   // reload the 'views' if the View Editor is open
      try {
        rmFx_View.ManageLoad();
      } catch(ex) {}
	}
}


function reminderFox_handleMigration(oldVersion) {
	// this is an older version; we need to handle migration code	
	if ( oldVersion <  "1.9.8" ) {		
		// Migrate old quick alarms
		
		var quickAlarms = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + REMINDER_FOX_QUICK_ALARMS);		
		if ( quickAlarms != null && quickAlarms.length > 0 ) {
			var beginIndex = quickAlarms.indexOf( "X-REMINDERFOX-VALARM:");
			if ( beginIndex != -1 ) { 
				var quickAlarmArray = new Array();
				if ( quickAlarms != null && quickAlarms.length > 0 ) {
					var currentAlarms = quickAlarms;
					beginIndex = currentAlarms.indexOf( "X-REMINDERFOX-VALARM:");
					while ( currentAlarms.length > 0 && beginIndex != -1 ) {
						var snoozeIndex = currentAlarms.indexOf( "X-REMINDERFOX-SNOOZE:");
						var endTextIndex = snoozeIndex;
						var notesText = null;
						// check for notes
						var notesIndex = currentAlarms.indexOf( "X-REMINDERFOX-NOTES:");
						if ( notesIndex != -1 && notesIndex < snoozeIndex ) {
							notesText = currentAlarms.substring( 
								notesIndex + "X-REMINDERFOX-NOTES:".length, snoozeIndex	);
							endTextIndex = notesIndex;
						}
						
						
						beginIndex = currentAlarms.indexOf( "X-REMINDERFOX-VALARM:");
						var alarmText = currentAlarms.substring( 
							beginIndex + "X-REMINDERFOX-VALARM:".length, endTextIndex	);
					
						if ( snoozeIndex != -1 ) {
							var snoozeTimeIndex = currentAlarms.indexOf( ";PT", snoozeIndex );
							if ( snoozeTimeIndex != -1 ) {
								var alarmTime = 	currentAlarms.substring( 
									snoozeIndex + "X-REMINDERFOX-SNOOZE:".length, snoozeTimeIndex	);
								var snoozeEndIndex = currentAlarms.indexOf( "M", snoozeTimeIndex );
								if ( snoozeEndIndex != -1 ) {
									var snoozeTime = currentAlarms.substring( 
										(snoozeTimeIndex + ";PT".length), snoozeEndIndex  );								
										
									var currentTime = new Date().getTime();
									var actualAlarmTime = parseInt( alarmTime ) - currentTime;
									
									var newQuickAlarm = 
										new ReminderFoxQuickAlarm( alarmText, notesText, alarmTime,  snoozeTime );
									quickAlarmArray[quickAlarmArray.length] = newQuickAlarm;
									
									currentAlarms = currentAlarms.substring(snoozeEndIndex + 1 );		
								}
							}									
						}
					}
					reminderFox_updateQuickAlarmPref( quickAlarmArray );
				}
			}
		} // end of 'Migrate old quick alarms'
		
		// migrate 'Default Views'              //gW_DefaultViews 2010-03 
     	rmFx_migrate_defaultView('Set');
	}
}







function reminderFox_getSortedIndexOfNewReminder(  reminderFoxEvents, newreminder, addUniqueOnly  ) {	
	var month = newreminder.date.getMonth();


	// We go through each reminder and then compare that reminder's month with 
	// the reminder-to-be-added month, and if the new month is less, add there;
	// if the months are equal, then compare the days and add appropriately. 
	for ( var i = 0; i < reminderFoxEvents.length; i++ ) {
		var reminder = reminderFoxEvents[i];
		
		// add current reminder before reminders from later months
		if (   month < reminder.date.getMonth()) { 
			return i;
		}
		// if they have the same month, then compare dates
		else if ( month == reminder.date.getMonth() ) {
			if ( newreminder.date.getDate()  <  reminder.date.getDate() ) {
				return i;
			}
			else if (  newreminder.date.getDate() == reminder.date.getDate() ) {					
				if ( addUniqueOnly && newreminder.summary == reminder.summary ) {
					// this reminder is already in the list; just ignore it
					return -1;
				}
				else {
					if ( !newreminder.allDayEvent ) { 
						// this is an hourly event.  Let's place it chronologically
						if ( reminder.allDayEvent ) {
							// the current reminder is all day; let's put chronological events 
							// first
							return i;
						}
						else {
							// the current reminder is an hour event as well; let's place them
							// chronologically.
							if ( newreminder.date.getHours() < reminder.date.getHours() || 
								( newreminder.date.getHours() == reminder.date.getHours() && newreminder.date.getMinutes() < reminder.date.getMinutes() )  ){
									return i;
							}						
						}
					}					 
					// if this is an Imp	ortant reminder, add it before other reminders of the same day
					else if ( newreminder.priority == REMINDER_PRIORITY_IMPORTANT  ) {
						return i;
					}
				}
			}
		}  // monthly			
	} // for
	
	return reminderFoxEvents.length;
}	

  function reminderFox_indexOf(aParent, aChild, overrideLast)  { 
    // -1 if it does not exist
    var children = aParent.childNodes;
    if ( children == null ) {
    	return null;
    }
    for (var x=0; x<children.length; x++) {
	    if (children[x] == aChild) {
			if ( overrideLast ) {
				return x;
			}
			else {
				return (x == children.length - 1) ? -1 : x;
			}
	    }
    }
    return null;
  }
  




function reminderFox_getSortedIndexOfNewTodo(  reminderFoxTodos, newTodo ) {
	// if current todo is important, add to start of list
    if (newTodo.priority == REMINDER_PRIORITY_IMPORTANT  ) {
		// insert at beginning
		return 0;
    }
    else {
    	// run through until find one that's not important, and add new one before it
		 for( var i = 0; i < reminderFoxTodos.length; i++) {
	        if ( !reminderFoxTodos[i].priority == REMINDER_PRIORITY_IMPORTANT  ) {
	        	if ( newTodo.showInTooltip ) {
					return i;
	        	}
	        	else {
	        		if ( !reminderFoxTodos[i].showInTooltip ) {
						return i;
	        		}
	        	}	        
	        }
		}
    }
	
	// if the reminder hasn't been added yet, then place it at the end
	return reminderFoxTodos.length;			
}
 
 function reminderFox_getValidDateForMonth( year, month, date ) {
	var lastValidDate = date;	

// ReminderLens CHANGE !!!
//	var lastDayOfMonth = xrRL.getLastDayOfMonth( year, month );
	var lastDayOfMonth = oeDatePicker.getLastDayOfMonth( year, month );
	if ( date > lastDayOfMonth ) {
		lastValidDate = lastDayOfMonth;
	}
	return lastValidDate;
}
 
 

function reminderFox_getAlarmInMinutes( alarm ) {
		if ( alarm == null ) {
			return null;
		}
		// example: TRIGGER;VALUE=DURATION: -PT30M
		var alarmTime = alarm;
		var result = null;						 
		var alarmIndex1 = alarmTime.indexOf( "-PT" );
		if ( alarmIndex1 != -1 ) {
			var alarmIndex2 = alarmTime.indexOf( "M", alarmIndex1 );
			if ( alarmIndex2 != -1 ) {
				alarmTime = alarmTime.substring( alarmIndex1 + "-PT".length, alarmIndex2 );		
				result = parseInt( alarmTime );	
			}
			else {
				alarmIndex2 = alarmTime.indexOf( "H", alarmIndex1 );
				if ( alarmIndex2 != -1 ) {
					alarmTime = alarmTime.substring( alarmIndex1 + "-PT".length, alarmIndex2 );		
					result = parseInt(alarmTime) * 60;
				}	
			}	
		}
		else {
			alarmIndex1 = alarmTime.indexOf( "-P" );
			if ( alarmIndex1 != -1 ) {
				var alarmIndex2 = alarmTime.indexOf( "D", alarmIndex1 );
				if ( alarmIndex2 != -1 ) {
					alarmTime = alarmTime.substring( alarmIndex1 + "-P".length, alarmIndex2 );		
					result = parseInt( alarmTime ) * 24 * 60;					
				}
			}
		}		
		return result;				 
}



// index is the number of the element you wish to remove
// from the array: reminderFoxEvents	
function reminderFox_removeElement(reminderFoxEvents, index) {

    for (index = index; index<reminderFoxEvents.length;index++) {
        // assigns the value of elementnr+1 to elementnr, so you move all items by 1
        reminderFoxEvents[index] = reminderFoxEvents[index + 1];
    }
    reminderFoxEvents.length=reminderFoxEvents.length-1;
}

// position is the number where you want to add the new element (reminder) into 
// the array: reminderFoxEvents	
function reminderFox_insertIntoArray(reminderFoxEvents, reminder, position) {
	var origLength = reminderFoxEvents.length;
	if ( position > origLength ) {
		position = origLength;
	}
	
	reminderFoxEvents.length = reminderFoxEvents.length + 1;

	for ( var i = origLength; i >=0; i-- ) {
		if ( i == position ) {
			reminderFoxEvents[i] = reminder;
			break;
		}
		else if ( i > position ) {
			reminderFoxEvents[i] = reminderFoxEvents[i-1];
		}
		else if ( i < position ) {
			break;
		}
	}
	
}
	

function reminderFox_generateUniqueReminderId(date) {
	if ( date == null ) { 
		date = new Date();
	}
	return date.getTime() + "-" + Math.round(900000000 + (Math.random() * 100000000));
}

function reminderFox_generateUniqueTodoId(date) {
	if ( date == null ) { 
		date = new Date();
	}
	return date.getTime() + Math.round(900000000 + (Math.random() * 100000000));
}	

	
	function reminderFox_getNextReminderOccurrence( reminder, originalDate, weekNumber, interval ) {
		var reminderCurrentDate = reminder.date;
		
		if ( reminder.recurrence.type  == REMINDER_RECURRENCE_YEARLY ) {
			// do nothing; should only be once occurrence per year			
		}
		else if ( reminder.recurrence.type  == REMINDER_RECURRENCE_YEARLY_DAY ) { 
			// do nothing; should only be once occurrence per year			
		}
		else 	if ( reminder.recurrence.type  == REMINDER_RECURRENCE_MONTHLY_DATE ) {
				var monthReminder = reminderFox_cloneReminderFoxEvent( reminder );		
				
				var month = reminderCurrentDate.getMonth();
				var year = reminderCurrentDate.getFullYear();
				month = month + interval;			 	
			 	while ( month >= 12 ) {
			 		month = month - 12;
			 		year = year + 1;
			 	}
			
			 	var dayVal = reminderFox_getValidDateForMonth( year, month, originalDate.getDate() );		
				monthReminder.date = new Date( year, month, dayVal, originalDate.getHours(), originalDate.getMinutes() );		
				
				return monthReminder;		 	
		}
		else if ( reminder.recurrence.type  == REMINDER_RECURRENCE_MONTHLY_DAY ) {
				var monthReminder = reminderFox_cloneReminderFoxEvent( reminder );		
				
				var month = reminderCurrentDate.getMonth();
				var year = reminderCurrentDate.getFullYear();
				month = month + interval;			 	
			 	while ( month >= 12 ) {
			 		month = month - 12;
			 		year = year + 1;
			 	}
			 	
				var reminderDay = originalDate.getDay();
				var nextMonthDate = new Date( year, month, 1 );
				var reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( nextMonthDate, reminderDay, weekNumber );
				monthReminder.date = new Date( year, month, reminderWeekDateThisMonth, originalDate.getHours(), originalDate.getMinutes() );				
				return monthReminder;		
		}
		else	if ( reminder.recurrence.type  == REMINDER_RECURRENCE_WEEKLY ) {	
			var weeklyReminder = reminderFox_cloneReminderFoxEvent( reminder );	
			var weeklyInterval = 1;
			if ( weeklyReminder.recurrence.interval != null  ) {
				weeklyInterval =  weeklyReminder.recurrence.interval;
			}
			weeklyReminder.date.setDate( weeklyReminder.date.getDate() + (weeklyInterval*7) );			
			return weeklyReminder;				
		}
		return null;			
	}
	
	function reminderFox_getFirstReminderOccurrenceAfterStartDate( reminder, initialStartDate ) {
		var startDate = new Date( initialStartDate.getFullYear(), initialStartDate.getMonth(), initialStartDate.getDate(), 
			initialStartDate.getHours(), initialStartDate.getMinutes() );
		var nexDate;
		var dayVal;		
		var finalDate;
		var todaysDate = new Date();
		var interval = 1;
		if ( reminder.recurrence.type  == REMINDER_RECURRENCE_ONETIME) {		
			return reminder;
		}
		else if ( reminder.recurrence.type  == REMINDER_RECURRENCE_YEARLY ) {
			var reminderOriginalDate = reminder.date;  
			// if start date is less than the default reminder date, return the reminder date
			if (  reminderFox_compareDates( startDate, reminderOriginalDate ) == -1 ) {
				return  reminderFox_cloneReminderFoxEvent( reminder );
			}
			
			
			if ( reminder.recurrence.interval != null && reminder.recurrence.interval > 1 ) {   // 2
				// if it's same year, just continue to normal logic;
				// otherwise, advance the year
				interval = reminder.recurrence.interval;
				if (  startDate.getFullYear() != reminderOriginalDate.getFullYear() ) {  
					
					// get the differnce and years, and add the value to the final date accordingly 	
					var yearsDiff = startDate.getFullYear() - reminderOriginalDate.getFullYear();
				    var modVal =  reminderFox_mod( yearsDiff , interval);
				    // if mod val == 0, then this year is valid; continue on 
			   		if ( modVal != 0 ) {
			   			var diff = interval - modVal;			    		
			     		startDate.setFullYear( startDate.getFullYear()+diff);
			     		dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() , reminderOriginalDate.getMonth(), reminderOriginalDate.getDate() );																				
						startDate.setDate(dayVal);			
						finalDate = new Date( startDate.getFullYear(), reminderOriginalDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );	
						
		     			var yearReminder = reminderFox_cloneReminderFoxEvent( reminder );
						yearReminder.date = finalDate;
						return yearReminder;	
			   		}
				}	   		
			}	
			if ( reminderOriginalDate.getMonth() < startDate.getMonth() ) {
				dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() + interval, reminderOriginalDate.getMonth(), reminderOriginalDate.getDate() );					
				finalDate = new Date( startDate.getFullYear() + interval, reminderOriginalDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes() );	
			}
			else if ( reminderOriginalDate.getMonth() > startDate.getMonth() ) {
				dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() , reminderOriginalDate.getMonth(), reminderOriginalDate.getDate() );								
				finalDate = new Date( startDate.getFullYear(), reminderOriginalDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
			}
			// same month
			else {
				if ( reminderOriginalDate.getDate() < startDate.getDate() ) {
					dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() + interval , reminderOriginalDate.getMonth(), reminderOriginalDate.getDate() );												
					finalDate = new Date( startDate.getFullYear() + interval, reminderOriginalDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes() );		
				}
				else if ( reminderOriginalDate.getDate() > startDate.getDate() ) {
					dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() , reminderOriginalDate.getMonth(), reminderOriginalDate.getDate() );																
					finalDate = new Date( startDate.getFullYear(), reminderOriginalDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
				}
				else {   // same date; return it
					dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() , reminderOriginalDate.getMonth(), reminderOriginalDate.getDate() );																				
					finalDate = new Date( startDate.getFullYear(), reminderOriginalDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
				}
			}
	
			var yearReminder = reminderFox_cloneReminderFoxEvent( reminder );
			yearReminder.date = finalDate;
			return yearReminder;
		}
		else if ( reminder.recurrence.type  == REMINDER_RECURRENCE_YEARLY_DAY ) { 
			var reminderOriginalDate = reminder.date;
			
			// if start date is less than the default reminder date, then use the reminder date as start date
			if (  reminderFox_compareDates( startDate, reminderOriginalDate ) == -1 ) {
				startDate = reminderOriginalDate;
			}
			
			if ( reminder.recurrence.interval != null && reminder.recurrence.interval > 1 ) {   // 2
				interval = reminder.recurrence.interval;
			
				// if it's same year, just continue to normal logic;
				// otherwise, advance the year
				if (  startDate.getFullYear() != reminderOriginalDate.getFullYear() ) {  
					// get the differnce and years, and add the value to the final date accordingly 	
					var yearsDiff = startDate.getFullYear() - reminderOriginalDate.getFullYear();
				    var modVal =  reminderFox_mod( yearsDiff , reminder.recurrence.interval);
				    // if mod val == 0, then this year is valid; continue on 
			   		if ( modVal != 0 ) {
			   			var diff = interval - modVal;			    		
			     		startDate.setFullYear( startDate.getFullYear()+diff);
			     		
			     		var reminderDay = reminderOriginalDate.getDay();
						var weekNumber = reminderFox_getWeekNumber( reminder.date );
						var nextYearStartDate = new Date( startDate.getFullYear(), reminderOriginalDate.getMonth(), reminderOriginalDate.getDate() );	
						var reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( nextYearStartDate, reminderDay, weekNumber );
						dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear(), reminderOriginalDate.getMonth(), reminderWeekDateThisMonth );			
						finalDate = new Date( startDate.getFullYear(), reminderOriginalDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );	
			     					     		
		     			var yearReminder = reminderFox_cloneReminderFoxEvent( reminder );
						yearReminder.date = finalDate;
						return yearReminder;	
			   		}
				}	   		
			}		

			if ( reminderOriginalDate.getMonth() < startDate.getMonth() ) {
				var reminderDay = reminderOriginalDate.getDay();
				var weekNumber = reminderFox_getWeekNumber( reminder.date );
				var nextYearStartDate = new Date( startDate.getFullYear() + interval, reminderOriginalDate.getMonth(), reminderOriginalDate.getDate() );	
				var reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( nextYearStartDate, reminderDay, weekNumber );
				dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() + interval, reminderOriginalDate.getMonth(), reminderWeekDateThisMonth );			
				finalDate = new Date( startDate.getFullYear() + interval, reminderOriginalDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );	
				}
			else if ( reminderOriginalDate.getMonth() > startDate.getMonth() ) {
				var reminderDay = reminderOriginalDate.getDay();
				var weekNumber = reminderFox_getWeekNumber( reminder.date );
				var nextYearStartDate = new Date( startDate.getFullYear(), reminderOriginalDate.getMonth(), reminderOriginalDate.getDate() );	
				var reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( nextYearStartDate, reminderDay, weekNumber );			
				dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() , reminderOriginalDate.getMonth(), reminderWeekDateThisMonth );								
				finalDate = new Date( startDate.getFullYear(), reminderOriginalDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
			}
			// same month
			else {
				var reminderDay = reminderOriginalDate.getDay();
				var weekNumber = reminderFox_getWeekNumber( reminder.date );
				
				var nextYearStartDate = new Date( startDate.getFullYear(), reminderOriginalDate.getMonth(), reminderOriginalDate.getDate() );	
				var reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( nextYearStartDate, reminderDay, weekNumber );
			
				if ( reminderWeekDateThisMonth < startDate.getDate() ) {
					nextYearStartDate = new Date( startDate.getFullYear() + interval, reminderOriginalDate.getMonth(), reminderOriginalDate.getDate() );	
					reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( nextYearStartDate, reminderDay, weekNumber );
					dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() + interval , reminderOriginalDate.getMonth(), reminderWeekDateThisMonth );												
					finalDate = new Date( startDate.getFullYear() + interval, reminderOriginalDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );		
				}
				else if ( reminderWeekDateThisMonth > startDate.getDate() ) {
					dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() , reminderOriginalDate.getMonth(), reminderWeekDateThisMonth );																
					finalDate = new Date( startDate.getFullYear(), reminderOriginalDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
				}
				else {   // same date; return it
					dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() , reminderOriginalDate.getMonth(), reminderWeekDateThisMonth );																				
					finalDate = new Date( startDate.getFullYear(), reminderOriginalDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
				}
			}
						
			var yearReminder = reminderFox_cloneReminderFoxEvent( reminder );
			yearReminder.date = finalDate;
			return yearReminder;		
		
		}		
		else 	if ( reminder.recurrence.type  == REMINDER_RECURRENCE_MONTHLY_DATE ) {
			var reminderOriginalDate = reminder.date;
			// if start date is less than the default reminder date, then use the reminder date as start date
			if (  reminderFox_compareDates( startDate, reminderOriginalDate ) == -1 ) {
				startDate = reminderOriginalDate;
			}
			
			if ( reminder.recurrence.interval != null && reminder.recurrence.interval > 1 ) {   // 2
				interval = reminder.recurrence.interval;
				var monthsDiff = reminderFox_computerNumberOfMonthsDifference( reminderOriginalDate, startDate);
				if ( monthsDiff != 0 ) {
				
					// get the differnce and years, and add the value to the final date accordingly 						
				    var modVal =  reminderFox_mod( monthsDiff , interval);
				    // if mod val == 0, then this month is valid; continue on 
			   		if ( modVal != 0 ) {
			   			var diff =interval - modVal;			    		
			     		startDate.setMonth( startDate.getMonth()+diff);
			     		
			     		dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() , startDate.getMonth(), reminderOriginalDate.getDate() );											
						finalDate = new Date( startDate.getFullYear(), startDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );							
						var monthReminder = reminderFox_cloneReminderFoxEvent( reminder );
						monthReminder.date = finalDate;
						return monthReminder;
					}
				}
			}
		
			
			// first check to see if the date of the reminder is less or more than start date.
			// if less, then we need to go to the next month;  if more, than we will use this month
			if ( reminderOriginalDate.getDate() < startDate.getDate() ) {
				var month = startDate.getMonth();
				var year = startDate.getFullYear();
				month = month + interval;			 	
			 	while ( month >= 12 ) {
			 		month = month - 12;
			 		year = year + 1;
			 	}
			 				 				 	
				var dayVal = reminderFox_getValidDateForMonth( year, month, reminderOriginalDate.getDate() );			 		
				finalDate = new Date( year, month, dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );		
			}
			else if ( reminderOriginalDate.getDate() > startDate.getDate() ) {
				dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() , startDate.getMonth(), reminderOriginalDate.getDate() );											
				finalDate = new Date( startDate.getFullYear(), startDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
			}
			else {   // same date; return it
				dayVal = reminderFox_getValidDateForMonth(  startDate.getFullYear() , startDate.getMonth(), reminderOriginalDate.getDate() );											
				finalDate = new Date( startDate.getFullYear(), startDate.getMonth(), dayVal, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );				
			}

			
			
			
			var monthReminder = reminderFox_cloneReminderFoxEvent( reminder );
			monthReminder.date = finalDate;
			return monthReminder;
		}
		else if ( reminder.recurrence.type  == REMINDER_RECURRENCE_MONTHLY_DAY ) {		
			var reminderOriginalDate = reminder.date;
			// if start date is less than the default reminder date, then use the reminder date as start date
			if (  reminderFox_compareDates( startDate, reminderOriginalDate ) == -1 ) {
				startDate = reminderOriginalDate;
			}
			
			var reminderDay = reminder.date.getDay();
			var weekNumber = reminderFox_getWeekNumber( reminder.date );
			
			if ( reminder.recurrence.interval != null && reminder.recurrence.interval > 1 ) {   // 2
				interval = reminder.recurrence.interval;
				var monthsDiff = reminderFox_computerNumberOfMonthsDifference( reminderOriginalDate, startDate);
				if ( monthsDiff != 0 ) {
					// get the differnce and years, and add the value to the final date accordingly 						
				    var modVal =  reminderFox_mod( monthsDiff , interval);
				    // if mod val == 0, then this month is valid; continue on 
			   		if ( modVal != 0 ) {
			   			var diff =interval - modVal;			    		
			     		startDate.setMonth( startDate.getMonth()+diff);
				     	var month = startDate.getMonth();
						var year = startDate.getFullYear();
		     			var reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( startDate, reminderDay, weekNumber );
		     		
		     			var dayVal = reminderFox_getValidDateForMonth( year, month, reminderWeekDateThisMonth );			
						var newDate = new Date( year, month, dayVal );		
						reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( newDate, reminderDay, weekNumber );
						finalDate = new Date( newDate.getFullYear(), newDate.getMonth(), reminderWeekDateThisMonth, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );			
						var monthReminder = reminderFox_cloneReminderFoxEvent( reminder );
						monthReminder.date = finalDate;
						return monthReminder;
					}
				}
			}
									
			var reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( startDate, reminderDay, weekNumber );
			
			// first check to see if the date of the reminder is less or more than start date.
			// if less, then we need to go to the next month;  if more, than we will use this month
			if ( reminderWeekDateThisMonth < startDate.getDate() ) {
				var month = startDate.getMonth();
				var year = startDate.getFullYear();
				month = month + interval;			 	
			 	while ( month >= 12 ) {
			 		month = month - 12;
			 		year = year + 1;
			 	}
				var dayVal = reminderFox_getValidDateForMonth( year, month, reminderWeekDateThisMonth );			
				var newDate = new Date( year, month, dayVal );		
				reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( newDate, reminderDay, weekNumber );
				finalDate = new Date( newDate.getFullYear(), newDate.getMonth(), reminderWeekDateThisMonth, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
			}
			else if ( reminderWeekDateThisMonth > startDate.getDate() ) {									
				finalDate = new Date( startDate.getFullYear(), startDate.getMonth(), reminderWeekDateThisMonth, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
			}
			else {   // same date; return it
				finalDate = new Date( startDate.getFullYear(), startDate.getMonth(), reminderWeekDateThisMonth, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );	
			}
			
			var monthReminder = reminderFox_cloneReminderFoxEvent( reminder );
			monthReminder.date = finalDate;
			return monthReminder;				
		}
		
		// WEEKLY 
		else	if ( reminder.recurrence.type  == REMINDER_RECURRENCE_WEEKLY ) {	
			var reminderOriginalDate = reminder.date;
			// if start date is less than the default reminder date, then use the reminder date as start date
			if (  reminderFox_compareDates( startDate, reminderOriginalDate ) == -1 ) {
				startDate = reminderOriginalDate;
			}
		
			var startDay = startDate.getDay();
			var targetYear = startDate.getFullYear();
			var targetMonth = startDate.getMonth();
			var weeklyReminder = reminderFox_cloneReminderFoxEvent( reminder );
			
			if ( reminder.recurrence.byDay != null && reminder.recurrence.byDay.indexOf( ",") != -1 ) {		
				var reminderDay = startDay;
				// first handle interval to get proper week
				var weeklyReminder = reminderFox_cloneReminderFoxEvent( reminder );
				weeklyReminder.date = new Date( startDate.getFullYear(), startDate.getMonth(), startDate.getDate(), startDate.getHours(), startDate.getMinutes()  );
				if ( reminder.recurrence.interval != null && reminder.recurrence.interval > 1 ) {   // 2
					interval = reminder.recurrence.interval;
					
					var dayValue = reminder.date.getDay();
					weeklyReminder = reminderFox_getThisDayFromCurrentWeeklyReminder( weeklyReminder, dayValue );
					
					var finalDate = new Date( weeklyReminder.date.getFullYear(), weeklyReminder.date.getMonth(), weeklyReminder.date.getDate(), reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
					// since this is alternating, determine if this week is the correct week, or if it is next week
					var numOfDaysDiff = reminderFox_computeNumberOfDaysDifference( reminder.date, finalDate );
				    var modVal=  reminderFox_mod( numOfDaysDiff , interval*7);
			   		if ( modVal != 0 ) {
			   			var diff =interval*7 - modVal;			   
			   		 	// we are an odd week away, need to add 7 to get to the next alternating week
			     		finalDate.setDate( finalDate.getDate() + diff );
			     		weeklyReminder.date = finalDate;
					}	
					weeklyReminder = reminderFox_getThisDayFromCurrentWeeklyReminder( weeklyReminder, 0 );  // reset date to Sunday
					reminderDay = 0; // reset to sunday
					// if the reminder original date is after the first date of this week, move ahead to that date...
					while (   reminderFox_compareDates( weeklyReminder.date, reminderOriginalDate ) == -1 ) {
						reminderDay ++;
						weeklyReminder.date.setDate( weeklyReminder.date.getDate() + 1);
					}
					while (   reminderFox_compareDates( weeklyReminder.date, startDate ) == -1 ) {
						reminderDay ++;
						weeklyReminder.date.setDate( weeklyReminder.date.getDate() + 1);
					}
					targetYear = weeklyReminder.date.getFullYear();
					targetMonth = weeklyReminder.date.getMonth();
				}	
				
				// here
				var increment = 0;
				while ( !reminderFox_isDayInByDayList( reminderDay, reminder.recurrence.byDay ) && increment < 8 ) {
					reminderDay++;
					if ( reminderDay >= 7  ) { // handle going past Saturday (6) and reset to Sunday (0)
						reminderDay = 0;
					}
					increment++;
				}	
				finalDate = new Date( targetYear,targetMonth, weeklyReminder.date.getDate() + increment, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
			}	
			else {
				var reminderDay = reminder.date.getDay();
				var compareCurrentDay = reminderDay + 1;
				var compareFirstDay = startDay + 1;  
				var daysDifference;
				if ( compareCurrentDay < compareFirstDay ) {
					compareCurrentDay = compareCurrentDay + 7;
				}	
				daysDifference = (compareCurrentDay - compareFirstDay);
				finalDate = new Date( startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + daysDifference, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
		
				if ( reminder.recurrence.interval != null && reminder.recurrence.interval > 1 ) {   // 2
					interval = reminder.recurrence.interval;
					// since this is alternating, determine if this week is the correct week, or if it is next week
					var numOfDaysDiff = reminderFox_computeNumberOfDaysDifference( reminder.date, finalDate );
				    var modVal=  reminderFox_mod( numOfDaysDiff , interval*7);
			   		if ( modVal != 0 ) {
			   			var diff =interval*7 - modVal;			   
			   		 	// we are an odd week away, need to add 7 to get to the next alternating week
			     		finalDate.setDate( finalDate.getDate() + diff );
					}	
				}		
			}		
			
			weeklyReminder.date = finalDate;
			return weeklyReminder;				
		
		}		
		else	if ( reminder.recurrence.type  == REMINDER_RECURRENCE_DAILY ) {	
			var reminderOriginalDate = reminder.date;
			// if start date is less than the default reminder date, return the reminder date
			if (  reminderFox_compareDates( startDate, reminderOriginalDate ) == -1 ) {
				return  reminderFox_cloneReminderFoxEvent( reminder );
			}
			
	     	var dailyReminder =   reminderFox_cloneReminderFoxEvent( reminder );
			if ( reminder.recurrence.interval != null && reminder.recurrence.interval > 1 ) {   // 2
				interval = reminder.recurrence.interval;
				var numOfDaysDiff = reminderFox_computeNumberOfDaysDifference( reminder.date, startDate );
				
		   		 var modVal =  reminderFox_mod( numOfDaysDiff , interval);
	   			 if ( modVal != 0 ) {
	   			 	var diff =interval - modVal;			    	
	   			 	// we are an odd week away, need to add 7 to get to the next alternating week
					dailyReminder.date =  new Date( startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + diff, reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
					return dailyReminder;			
				}	
			}		
																		
			dailyReminder.date =  new Date( startDate.getFullYear(), startDate.getMonth(), startDate.getDate(), reminderOriginalDate.getHours(), reminderOriginalDate.getMinutes()  );
			return dailyReminder;			
		}	
		return null;
	}
	
function reminderFox_mod(divisee,base) {
	return Math.round(divisee - (Math.floor(divisee/base)*base));
}

function reminderFox_isDayInByDayList( dayNum, byDayList ) {
	if ( dayNum == 0 ) {
		return byDayList.indexOf( "SU" ) != -1;
	}
	else if ( dayNum == 1 ) {
		return byDayList.indexOf( "MO" ) != -1;
	}
	else if ( dayNum == 2 ) {
		return byDayList.indexOf( "TU" ) != -1;
	}
	else if ( dayNum == 3 ) {
		return byDayList.indexOf( "WE" ) != -1;
	}
	else if ( dayNum == 4 ) {
		return byDayList.indexOf( "TH" ) != -1;
	}
	else if ( dayNum == 5 ) {
		return byDayList.indexOf( "FR" ) != -1;
	}
	else if ( dayNum == 6 ) {
		return byDayList.indexOf( "SA" ) != -1;
	}
	return false;
}

function reminderFox_computerNumberOfMonthsDifference( startDate, endDate ) {				
		var monthCount = 0;
		var finalMonth;
		var startYear = startDate.getFullYear();
		var startMonth = startDate.getMonth();
		var endYear = endDate.getFullYear();
		if ( endYear > startYear ) {
		    finalMonth = 12;
		    monthCount += endDate.getMonth() + 1; // +1 for month 0-based offset
		    
		    endYear--;
		    while ( endYear > startYear ) {
		        monthCount += 12;
		        endYear--;
		    }
		}
		else {
		    finalMonth = endDate.getMonth() + 1;
		}
	
		monthCount += (finalMonth - (startMonth+1));
		return monthCount;
		
	}



function reminderFox_computeNumberOfDaysDifference( origStartDate, origEndDate ) {
	var startDate = new Date( origStartDate.getFullYear(), origStartDate.getMonth(), origStartDate.getDate(), 0, 0, 0 );
	var finalDate = new Date( origEndDate.getFullYear(), origEndDate.getMonth(), origEndDate.getDate(), 0, 0, 0 );
	
    // The number of milliseconds in one day
    var ONE_DAY = 1000 * 60 * 60 * 24

    // Convert both dates to milliseconds
    var date1_ms = startDate.getTime()
    var date2_ms = finalDate.getTime()

    // Calculate the difference in milliseconds
    var difference_ms = Math.abs(date1_ms - date2_ms)
    
    // Convert back to days and return
    var numOfDaysDiff =  Math.round(difference_ms/ONE_DAY);
    return numOfDaysDiff;
 }
	
function reminderFox_getWeekNumber( currentDate ) {
		var reminderDate = currentDate.getDate();
		var numberOfDay = reminderDate / 7;
		var intvalue =	parseInt( numberOfDay );
		if ( reminderDate % 7 == 0 ) {
			intvalue--;
		}
		var weekNumber = intvalue + 1;   // 0-based index
		if ( weekNumber == 5 ) {
			weekNumber = -1;  // set to last week of month
		}
		return weekNumber;
}
	
function reminderFox_getWindowEnumerator() {
	var windowManager = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService();
	var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
	var windowEnumerator = windowManagerInterface.getEnumerator("navigator:browser");
	if ( windowEnumerator.hasMoreElements() ) {
		return windowEnumerator;
	}

	 windowEnumerator = windowManagerInterface.getEnumerator("mail:3pane");
	if ( windowEnumerator.hasMoreElements() ) {
		return windowEnumerator;
	}	
	
	windowEnumerator = windowManagerInterface.getEnumerator("mail:messageWindow");
	if ( windowEnumerator.hasMoreElements() ) {
		return windowEnumerator;
	}	
	
	windowEnumerator = windowManagerInterface.getEnumerator("calendarMainWindow");
	if ( windowEnumerator.hasMoreElements() ) {
		return windowEnumerator;
	}	
	
	
	
	return windowManagerInterface.getEnumerator("navigator:browser");
	
}
	
function reminderFox_playSound() {
	var gSound = Components.classes["@mozilla.org/sound;1"].createInstance(Components.interfaces.nsISound);
	var savefilePath;
	// check if user has specified a specific file path for sound in their preferences
	try {
		savefilePath = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_ALARM_SOUND_PATH);
	}
	catch ( e) {
	}
	// if not, then play default beep sound
	if ( savefilePath == null || savefilePath == "" ) {
		gSound.beep();	
	}
	else {
	    var _ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
	    var _soundService = Components.classes["@mozilla.org/sound;1"].createInstance(Components.interfaces.nsISound);
	    _soundService.init();
	  
	    var uri = null;
	    try {
	      var localFile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
	      localFile.initWithPath(savefilePath);
	      
	      if (localFile.exists())
	        uri = _ioService.newFileURI(localFile);
	    } catch(e) {
	      uri = _ioService.newURI(aPath, null, null);
	    }
	    
	    if (uri)
	      _soundService.play(uri)
	}
}
	
	function reminderFox_getDateForSpecifiedWeekNumber( currentDate, dayNumber, weekNumber ) {  
		var firstDate = new Date( currentDate.getFullYear(), currentDate.getMonth(), 1 );  
		var firstDayOfMonth = firstDate.getDay();
		
		// calculate the date that the first day-of-week falls on (using the day of the first of the month)
		var compareCurrentDay = dayNumber + 1;
		var compareFirstDay = firstDayOfMonth + 1;
		if ( compareCurrentDay < compareFirstDay ) {
			compareCurrentDay = compareCurrentDay + 7;
		}
		var firstWeekDateVal = (compareCurrentDay - compareFirstDay) + 1;
		var finalDate;
		
		// we have the date that the first day-of-week falls on.  Now let's calculate the Nth day of week
		if ( weekNumber == -1 ) {  // last day of week of the month
			var weekNumberCalculation = 5 - 1;
			finalDate  = firstWeekDateVal + ( weekNumberCalculation*7);
			var lastDayOfMonth = oeDatePicker.getLastDayOfMonth( currentDate.getFullYear(), currentDate.getMonth() );
			if ( finalDate > lastDayOfMonth ) {
				finalDate  = finalDate - 7;   // previous (4th) week must be the last week of this month
			}
		}
		else {
			var weekNumberCalculation = weekNumber - 1;
			finalDate  = firstWeekDateVal + ( weekNumberCalculation*7);
		}
		return finalDate;
	}	
	
function reminderFox_getSortNewUpcomingReminderIndex( reminders, newreminder  ) {
	// We go through each reminder and then compare that reminder's month with 
	// the reminder-to-be-added month, and if the new month is less, add there;
	// if the months are equal, then compare the days and add appropriately. 

	// first check if the new reminder is greater than the last sorted reminder.  If so, add to 
	// end of the list...
	if ( reminders.length > 0 && reminderFox_compareReminderDatesAndTimes( newreminder, reminders[reminders.length-1] ) !=-1 ) {
			return reminders.length;
	}

	// otherwise, go through the list and insert where the new reminder is less than 
	// the reminders in the list
	for( var i = 0; i < reminders.length; i++ ) {
		var currentReminder = reminders[i];		
		if (  reminderFox_compareReminderDatesAndTimes( newreminder, currentReminder ) == -1 ) {
			return i;
		}
	}	 

 	// if the reminder hasn't been added yet, then place it at the end
	// of the list
	return reminders.length;
}


//function reminderFox_getAllTodosInDateRangeOrig( startDate, endDate ) {
//	var allTodosArray = { };
//	var i;
//	var reminderFoxTodosArrayArg =  reminderFox_getReminderTodos();
//	for ( var n in reminderFoxTodosArrayArg ) {
//		var reminderTodos = reminderFoxTodosArrayArg[n];
//		for (  i = 0; i < reminderTodos.length; i++ ) {
//			var reminderTodo = reminderTodos[i];
//			if ( reminderTodo.date != null &&  
//				( (reminderFox_compareDates( reminderTodo.date, startDate ) != -1) &&
//				  (reminderFox_compareDates( reminderTodo.date, endDate ) != 1) ) ) {
//				
//					if ( 	allTodosArray[n] == null ) {
//						allTodosArray[n] = new Array();
//					}
//					var currentTodosList  = allTodosArray[n];
//				
//					currentTodosList[currentTodosList.length] = reminderTodo;
//			}
//		}	
//	}
//	return allTodosArray;
//}


function reminderFox_getAllTodosInDateRange( startDate, endDate ) {
	var allTodosArray = { };
	var i;
	var reminderFoxTodosArrayArg =  reminderFox_getReminderTodos();
	for ( var n in reminderFoxTodosArrayArg ) {
		var reminderTodos = reminderFoxTodosArrayArg[n];
		for (  i = 0; i < reminderTodos.length; i++ ) {
			var reminderTodo = reminderTodos[i];
			if ( reminderTodo.date != null ) {				
				var allReminders = reminderFox_getAllRemindersInDateRange( reminderTodo,  startDate, endDate, false );
						
				if ( allTodosArray[n] == null ) {
					allTodosArray[n] = new Array();
				}
				var currentTodosList  = allTodosArray[n];
				for ( var j = 0; j < allReminders.length; j++ ) {				
					currentTodosList[currentTodosList.length] = allReminders[j];
				}				
			}
		}	
	}
	return allTodosArray;
}


function reminderFox_getAllTodosInDateRangeForGivenList( todoList, startDate, endDate ) {
	var dateTodos = new Array();
	var i;
	
	for (  i = 0; i < todoList.length; i++ ) {
		var reminderTodo = todoList[i];
		if ( reminderTodo.date != null &&  
			( (reminderFox_compareDates( reminderTodo.date, startDate ) != -1) &&
			  (reminderFox_compareDates( reminderTodo.date, endDate ) != 1) ) ) {

				dateTodos[dateTodos.length] = reminderTodo;
		}
	}	
	
	return dateTodos;
}


function reminderFox_getAllTodosInDateRangeForGivenListMultiples( todoList, startDate, endDate ) {
	var dateTodos = new Array();
	var i;
	
	for (  i = 0; i < todoList.length; i++ ) {
		var reminderTodo = todoList[i];
		if ( reminderTodo.date != null ) {				
			var allReminders = reminderFox_getAllRemindersInDateRange( reminderTodo,  startDate, endDate, true );			
			for ( var j = 0; j < allReminders.length; j++ ) {				
				dateTodos[dateTodos.length] = allReminders[j];				
			}
		}
	}	
	
	return dateTodos;
}
 
	
	function reminderFox_getAllRemindersInDateRange( reminder, initialStartDate, endDate, limitWeeklyReminders ) { 	
		var startDate = new Date( initialStartDate.getFullYear(), initialStartDate.getMonth(), initialStartDate.getDate(), 
			initialStartDate.getHours(), initialStartDate.getMinutes() );
		
		var reminderArray = new Array();
		var i;
		// if the reminder's recurrence enddate is less than the end date, use it as the end point
		if ( reminder.recurrence.endDate != null ) {
			if ( reminderFox_compareDates( reminder.recurrence.endDate, endDate ) == -1 ) {
				endDate = reminder.recurrence.endDate;
			}
		}

		// if reminder date is greater than the end date, then return empy array
		if ( reminderFox_compareDates( reminder.date, endDate ) == 1 ) {
			return reminderArray;
		}
		
		// if reminder date is greater than the start date, use the reminder date as the 
		// starting date
		if ( reminderFox_compareDates( reminder.date, startDate ) == 1 ) {
			startDate = reminder.date;
		}
 
		if ( reminder.recurrence.type  == REMINDER_RECURRENCE_ONETIME ) { 
			if ( reminderFox_compareDates( reminder.date, endDate ) == 1 ) {
				// return nothing if the reminder is outside of the ending date
				return reminderArray;
			}
			else if ( reminderFox_compareDates( reminder.date, startDate ) == -1 ) {
				// return nothing if the reminder has already occurred prior to the starting date
				
				// unless it's marked as Remind Until Completed...  then return it if today 
				// falls within the date range
			 	if ( reminder.remindUntilCompleted != null && reminder.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED ) {
			 		var todaysDate = new Date();
			 		if ( reminderFox_compareDates( todaysDate, startDate ) != -1 && 
			 		  reminderFox_compareDates( todaysDate, endDate )  != 1 ) {
				 		reminderArray[0] = reminder;
				 	}
		 		}
			
				return reminderArray;
			}	
			else {
				reminderArray[0] = reminder;
				return reminderArray;
			}
		}	
		else if ( reminder.recurrence.type  == REMINDER_RECURRENCE_YEARLY ) { 
			var yearReminder = reminderFox_getFirstReminderOccurrenceAfterStartDate( reminder, startDate );
			if ( yearReminder != null  ) {
				if ( reminderFox_compareDates( yearReminder.date, endDate ) == 1 ) {
					// return nothing if the reminder is outside of the ending date
					return reminderArray;
				}
				else {
					reminderArray[0] = yearReminder;
					return reminderArray;
				}		
			}
			return reminderArray;
		}
		else if ( reminder.recurrence.type  == REMINDER_RECURRENCE_YEARLY_DAY ) { 
			var yearReminder = reminderFox_getFirstReminderOccurrenceAfterStartDate( reminder, startDate );

			if ( yearReminder != null  ) {
				if ( reminderFox_compareDates( yearReminder.date, endDate ) == 1 ) {
					// return nothing if the reminder is outside of the ending date
					return reminderArray;
				}
				else {
					reminderArray[0] = yearReminder;
					return reminderArray;
				}		
			}
			return reminderArray;
		}				
		else 	if ( reminder.recurrence.type  == REMINDER_RECURRENCE_MONTHLY_DATE ) {
			var arrayIndex = 0;
			var monthReminder = reminderFox_getFirstReminderOccurrenceAfterStartDate( reminder, startDate );
			if ( monthReminder != null  ) {
				if ( reminderFox_compareDates(  monthReminder.date, endDate ) == 1 ) {
					// return nothing if the reminder is outside of the ending date
					return reminderArray;
				}							
				
				
				var interval = 1; 
				if ( reminder.recurrence.interval != null ) {
					interval =reminder.recurrence.interval;
				}
							
				while ( reminderFox_compareDates( monthReminder.date, endDate ) != 1 ) {				
					reminderArray[arrayIndex] = monthReminder;					
					monthReminder = reminderFox_getNextReminderOccurrence( monthReminder, reminder.date, 0, interval  );
					arrayIndex++;
				}
			}
			return reminderArray;
		}
		else if ( reminder.recurrence.type  == REMINDER_RECURRENCE_MONTHLY_DAY ) {
			var arrayIndex = 0;
			var monthReminder = reminderFox_getFirstReminderOccurrenceAfterStartDate( reminder, startDate );
			if ( monthReminder != null  ) {
				if ( reminderFox_compareDates(  monthReminder.date, endDate ) == 1 ) {
					// return nothing if the reminder is outside of the ending date
					return reminderArray;
				}	
				var weekNumber = reminderFox_getWeekNumber( reminder.date );							
				var interval = 1; 
				if ( reminder.recurrence.interval != null ) {
					interval =reminder.recurrence.interval;
				}							
				while ( reminderFox_compareDates( monthReminder.date, endDate ) != 1 ) {				
					reminderArray[arrayIndex] = monthReminder;					
					monthReminder = reminderFox_getNextReminderOccurrence( monthReminder, reminder.date, weekNumber, interval  );
					arrayIndex++;
				}
			}
			return reminderArray;		

		}
		else	if ( reminder.recurrence.type  == REMINDER_RECURRENCE_WEEKLY ) {	
			var arrayIndex = 0;
			var weeklyReminder = reminderFox_getFirstReminderOccurrenceAfterStartDate( reminder, startDate );
			if ( weeklyReminder != null  ) {
				if ( reminderFox_compareDates(  weeklyReminder.date, endDate ) == 1 ) {
					// return nothing if the reminder is outside of the ending date
					return reminderArray;
				}		
								
				var result = reminderFox_getDayAndEndDayOfYear( weeklyReminder, endDate );
				var dayOfYear = result.dayResult;
				var endDayOfYear  = result.endResult;				
				
				var endIndex = 365;
				if ( limitWeeklyReminders ) {
					endIndex = 8;
				}
				
				interval = 1;
				if ( reminder.recurrence.interval != null && reminder.recurrence.interval > 1 ) {   // 2
					interval = reminder.recurrence.interval;					
				}	
				interval = 7 * interval; // to get weeks
				
				if ( reminder.recurrence.byDay != null && reminder.recurrence.byDay.indexOf( ",") != -1 ) {					
					while ( dayOfYear <= endDayOfYear && arrayIndex < endIndex) {
						var reminderDay = weeklyReminder.date.getDay();
						var origDate = weeklyReminder.date.getDate();
						weeklyReminder	= reminderFox_cloneReminderFoxEvent(weeklyReminder);
						while ( reminderDay < 7 && dayOfYear <= endDayOfYear && arrayIndex < endIndex ) { 
							if ( reminderFox_isDayInByDayList( reminderDay, reminder.recurrence.byDay ) ) {
								reminderArray[arrayIndex] = weeklyReminder;	
								arrayIndex++;			
							}
							weeklyReminder	= reminderFox_cloneReminderFoxEvent(weeklyReminder);
							weeklyReminder.date.setDate( weeklyReminder.date.getDate() + 1);
							reminderDay++;
							dayOfYear++;  
						}
 				 		weeklyReminder	= reminderFox_cloneReminderFoxEvent(weeklyReminder);
						weeklyReminder.date = new Date( weeklyReminder.date.getFullYear(), weeklyReminder.date.getMonth(), weeklyReminder.date.getDate() + (interval-7), weeklyReminder.date.getHours(), weeklyReminder.date.getMinutes()  );
						dayOfYear = dayOfYear + (interval-7);		// -7 b/c end of this week
					}
				}	  
 				else {									
					while ( dayOfYear <= endDayOfYear && arrayIndex < endIndex) {
						reminderArray[arrayIndex] = weeklyReminder;	
						
						weeklyReminder	= reminderFox_cloneReminderFoxEvent(weeklyReminder);
						weeklyReminder.date = new Date( weeklyReminder.date.getFullYear(), weeklyReminder.date.getMonth(), weeklyReminder.date.getDate() + interval, weeklyReminder.date.getHours(), weeklyReminder.date.getMinutes()  );
						arrayIndex++;				
						dayOfYear = dayOfYear + interval;
					
					}
 				}
			}
			
			return reminderArray;				
		}	
		else if ( reminder.recurrence.type  == REMINDER_RECURRENCE_DAILY) {	
			var arrayIndex = 0;
			var dailyReminder = reminderFox_getFirstReminderOccurrenceAfterStartDate( reminder, startDate );
		
			if ( dailyReminder != null  ) { 
			if ( reminderFox_compareDates(  dailyReminder.date, endDate ) == 1 ) {
					// return nothing if the reminder is outside of the ending date
					return reminderArray;
				}					
								
				var result = reminderFox_getDayAndEndDayOfYear( dailyReminder, endDate );
				var dayOfYear = result.dayResult;
				var endDayOfYear  = result.endResult;
				
				var interval = 1;
				if ( reminder.recurrence.interval != null ) { 
					interval = reminder.recurrence.interval;					
				}		
				
				var endIndex = 365;
				if ( limitWeeklyReminders ) {   
					var	endIndex = 8;
				}
				while ( dayOfYear <= endDayOfYear && arrayIndex < endIndex) {
					reminderArray[arrayIndex] = dailyReminder;	
					
					dailyReminder	= reminderFox_cloneReminderFoxEvent(dailyReminder);
					dailyReminder.date = new Date( dailyReminder.date.getFullYear(), dailyReminder.date.getMonth(), dailyReminder.date.getDate() + interval, dailyReminder.date.getHours(), dailyReminder.date.getMinutes()  );
					arrayIndex++;				
					dayOfYear = dayOfYear + interval;				
				}												
			}
			return reminderArray;					
		}				
		return null;
	}
	
	function reminderFox_getFirstDayValueFromByDay( byday ) {
		var commaIndex = byday.indexOf(",");
		var firstDay;
		if ( commaIndex == -1 ) {
			firstDay = byday;
		}
		else {
			firstDay = byday.substring(0,commaIndex);
		}
		
		if ( firstDay == "SU") {
			return 0;
		}
		else if ( firstDay == "MO") {
			return 1;
		}
		else if ( firstDay == "TU") {
			return 2;
		}
		else if ( firstDay == "WE") {
			return 3;
		}
		else if ( firstDay == "TH") {
			return 4;
		}
		else if ( firstDay == "FR") {
			return 5;
		}
		else if ( firstDay == "SA") {
			return 6;
		}		
		else {
			return -1;
		}									
	}
	
	function reminderFox_getThisDayFromCurrentWeeklyReminder( reminder, targetDay )  { // this will see the current day, and move forward/back to get to the specified day
		var dateDay = reminder.date.getDay();
		if ( dateDay == targetDay ) {
			return reminder;
		}
		else if ( dateDay < targetDay ) { 
			reminder.date.setDate( reminder.date.getDate() + (targetDay-dateDay));
		}
		else if ( dateDay > targetDay ) { 
			reminder.date.setDate( reminder.date.getDate() - (dateDay-targetDay));
		}
		return reminder;
	}
	
	function reminderFox_getThisDayFromCurrentDate( currentDate, targetDay )  { // this will see the current day, and move forward/back to get to the specified day
		var dateDay = currentDate.getDay();
		if ( dateDay == targetDay ) {
			return currentDate;
		}
		else if ( dateDay < targetDay ) { 
			currentDate.setDate( currentDate.getDate() + (targetDay-dateDay));
		}
		else if ( dateDay > targetDay ) { 
			currentDate.setDate( currentDate.getDate() - (dateDay-targetDay));
		}
		
		return currentDate;
	}
	
	
	function reminderFox_getDayAndEndDayOfYear( weeklyReminder, endDate) {
		var dayArray;
		var month = weeklyReminder.date.getMonth();
		var day = weeklyReminder.date.getDate();
		var currentYear = weeklyReminder.date.getFullYear();
		if (reminderFox_isLeapYear(currentYear) ) {
			dayArray = REMINDER_FOX_lDOMonth;
		}
		else {
			dayArray = REMINDER_FOX_DOMonth;
		}
	
		var dayOfYear=0;
		for (var  i=0; i < month; i++) {
			dayOfYear += dayArray[i];
		}
		dayOfYear += day;		

		var endDayOfYear=0;
		if ( endDate.getFullYear() != currentYear ) {
			if (reminderFox_isLeapYear(endDate.getFullYear() ) ) {
				dayArray = REMINDER_FOX_lDOMonth;
			}
			else {
				dayArray = REMINDER_FOX_DOMonth;
			}
			endDayOfYear += 365;
		}
		month = endDate.getMonth();
		day = endDate.getDate();

		for ( i=0; i < month; i++) {
			endDayOfYear += dayArray[i];
		}
		endDayOfYear += day;	
		var result = { dayResult: dayOfYear, endResult:  endDayOfYear};
		return result;
	}
	

function reminderFox_compareReminderDatesAndTimes( reminder1, reminder2, dateOne, dateTwo ) {	
	if ( dateOne == null ) {
		dateOne = reminder1.date;
	}
	if ( dateTwo == null ) {
		dateTwo = reminder2.date;
	}
	var compare = reminderFox_compareDates( dateOne, dateTwo );
	if ( compare == 0 ) {
		if ( dateOne.getHours() < dateTwo.getHours() ) {
			// we want allDayEvents to occur after specific time events
			if ( reminder1.allDayEvent ) {
				return 1;
			}
			else {
				return -1;
			}
		}
		else if ( dateOne.getHours() > dateTwo.getHours() ) {
			// we want allDayEvents to occur after specific time events
			if ( reminder2.allDayEvent ) {
				return -1;
			}
			else {
				return 1;
			}
		}
		else {
			if ( dateOne.getMinutes() < dateTwo.getMinutes() ) {
				return -1;
			}
			else if ( dateOne.getMinutes() > dateTwo.getMinutes() ) {
				return 1
			}
			else {
				if ( dateOne.getSeconds() < dateTwo.getSeconds() ) {
					return -1;
				}
				else if ( dateOne.getSeconds() > dateTwo.getSeconds() ) {
					return 1
				}	
				else {
					return 0; // identical times
				}			
			}			
		}
	}
	
	return compare;
}
	
// return -1 if dateOne < dateTwo
// return 0 if equal
// return 1 if dateOne > dateTwo
function reminderFox_compareDates( dateOne, dateTwo ) {
	if (dateOne == null && dateTwo != null) {
		return -1;
	}
	if (dateTwo == null && dateOne != null) {
		return 1;
	}
	if (dateOne == null && dateTwo == null) {
		return 0;
	}
	
	var t1 = dateOne.getTime();
	var t2 = dateTwo.getTime();

    // Calculate the difference in milliseconds
    var difference_ms = t1 - t2;
    
    // if within one day, check to see if the dates are the same
    if ( difference_ms != 0 && difference_ms <= REMINDER_FOX_ONE_DAY && 
    	difference_ms >= REMINDER_FOX_NEGATIVE_ONE_DAY ) { 
    	if ( dateOne.getDate() == dateTwo.getDate() ) {
    		return 0;    		
    	}
	}
	
	if ( t1 < t2 ) {
		return -1;
	}
	else if ( t1 > t2 ) {
		return 1;
	}
	else{
		return 0;
	}		
}

var rmFx_OSinfo;

//gW_OSswitching    mods/adds  to support OS switching -------------		
function rmFx_opSystemInfo () {

	if (rmFx_OSinfo != null) { return  rmFx_OSinfo;}

	if ("nsIXULRuntime" in Components.interfaces) {
		var osInfo = Components.classes["@mozilla.org/xre/app-info;1"]
				.getService(Components.interfaces.nsIXULRuntime);
		rmFx_OSinfo =  osInfo.OS;
		var platform =  osInfo.XPCOMABI
	} else {
		var osInfo = Components.classes["@mozilla.org/network/protocol;1?name=http"]
				.getService(Components.interfaces.nsIHttpProtocolHandler);
		rmFx_OSinfo = (osInfo.oscpu == "Windows NT 5.1") ? "WINNT" : osInfo.oscpu;
		var platform =  osInfo.platform;
	}
	// 	 WINNT(x86-msvc)		 WINNT(Windows)
	// 	 Linux(x86-gcc3)		 
	// 	 Darwin(x86-gcc3) 					 
	
	reminderFox_logMessageLevel("OSinfo : " 
		+ rmFx_OSinfo + "(" + platform + ")  \n"
		+ navigator.userAgent, REMINDER_FOX_LOG_LEVEL_INFO);
	
	return rmFx_OSinfo;	
}

   /**
    * Store the prefs 'REMINDER_FOX_STORE_FILE' with osTyp
    * 
<br>	new storeFile concept:
<ul>	 	OS={ostype}:{osstring},OS={ostype}:{osstring},
<br>	 		fe:   OS=WINNT:D:\..\reminder.ics,OS=LINUX:/opt/../reminder.ics,OS=DARWIN:/home/user/.../reminder.ics,
</ul>
	   @param   filePath2store:	the 'local' file path
       @return  storeString4thisOS
    */
function rmFx_storeFile4OS(filePath2store) {
	var osTyp = rmFx_opSystemInfo();
	var storeFile;
	var osString = "";
	
	var storeString4thisOS = rmFx_getStoreFile4OS();
	
   try {
      var storeString = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_STORE_FILE);
   } 	catch ( e ) { var storeString = "";}	

	if (storeString != "" ) { 
		//  replace the 'storeString4thisOS' with 'filePath2store' if not ''
		var osArray = storeString.split("OS=");
		
		if (osArray.length > 0) {
			for (var nOS=0; nOS < osArray.length; nOS++) {
				var cString = osArray[nOS];
				
				if (cString.indexOf(osTyp +":") == 0) {
					// current OS found !! skip it

				} else {
					// replace entry with leading "OS="
					if (cString != "") {
						if (cString.substring(cString.length -1) != ",") {
							cString += ",";
						}						
					osString += "OS=" + cString;
					}
				}
 			}
		}
	}

	if (filePath2store != "") {
		osString += "OS=" + osTyp + ":" + filePath2store + ","; 
	}
	reminderFox_prefsBranch.setCharPref(REMINDER_FOX_STORE_FILE, osString);

	// reminderFox_logMessageLevel("storeString4thisOS : " + storeString4thisOS, 2);
	// reminderFox_logMessageLevel("osString : " + osString, 2);

	return storeString4thisOS;		  
}

// get the REMINDER_FOX_STORE_FILE for current OS
function rmFx_getStoreFile4OS() {
	var osTyp = rmFx_opSystemInfo();
	var storeString = "";

   try {
      storeString = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_STORE_FILE);
   } catch (ex) { 
		storeString = reminderFox_getReminderStoreFile();
	}

	var fnd = storeString.indexOf("OS=" + osTyp + ":");
   if (fnd > -1) {
		//for the current osTyp we have a 'storeFile', search it
		var osArray = storeString.split("OS=");
			for (var nOS=0; nOS < osArray.length; nOS++) {
				var cString = osArray[nOS];
				if (cString.substring(cString.length -1) == ",") {
					cString = cString.substring(0, cString.length-1);
				}
				fnd = cString.indexOf(osTyp + ":");
				if (fnd == 0) {
					var len = (osTyp + ":").length;
					storeString = cString.substring(len) ;
				}
			}
   } else {
   	storeString = "";
   }
	// reminderFox_logMessageLevel("storeString : " +  storeString, 2);

	return storeString;
}


   /**
    * Call filePicker
    *
    * @param   windowText:           FilePicker Window text
    * @param   filterName:           description of search filter,  eg. 'ICS file'
    * @param   defaultExtension:     the extension for 'FilterName' eg. '.ICS'
    * @param   defaultString:        eg. 'reminderfox.ics'  or '*.*'        
    * @param   mode:                 filePicker 'mode': 'modeOpen'=0 | 'modeSave'=1 | 'getFolder'=2 
    * disabled : param   prefsName:            reminderfox constant, to be use to save picked file to 'prefs'
    * @return  file (object)
 */
function rmFx_filePicker (windowText, filterName, defaultExtension, defaultString, prefsName, mode) {

	const nsIFilePicker = Components.interfaces.nsIFilePicker; 

	var picker = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);  
//	picker.appendFilters( 2); // nsIFilePicker.filterAll);
	picker.appendFilter( filterName, "*." + defaultExtension);    
	picker.defaultString = defaultString;
	picker.defaultExtension = defaultExtension;
    picker.init(window, windowText, mode /*nsIFilePicker.modeOpen*/);

    var rv = picker.show();
    if ((rv == nsIFilePicker.returnOK) || (rv == nsIFilePicker.returnReplace))  {
        var file = picker.file;
    //    reminderFox_prefsBranch.setCharPref(prefsName, file.path); 
        return file;                                    
    }  
    else  {
    //    reminderFox_prefsBranch.setCharPref(prefsName, "");
        return null;
    }
}
   /**
    * Call dirPicker
    *
    * @param   windowText:           FilePicker Window text
    * @param   filterName:           description of search filter,  eg. 'ICS file'
    * @param   defaultExtension:     the extension for 'FilterName' eg. '.ICS'
    * @param   defaultString:        eg. 'reminderfox.ics'  or '*.*'        
    * @param   prefsName:            reminderfox constant, to be use to save picked file to 'prefs'
    * @return  file (object)
 */
 
function rmFx_dirPicker (windowText, filterName, defaultExtension, defaultString) {

    const nsIFilePicker = Components.interfaces.nsIFilePicker; 

    var picker = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);  

    picker.defaultExtension = defaultExtension;
    picker.defaultString = defaultString;
    picker.init(window, windowText, nsIFilePicker.modeSave );

    var rv = picker.show();
    if (rv == nsIFilePicker.returnOK)  {
        var file = picker.file;
        return file;                                    
    }  
    else  {
        return null;
    }
}

//OSswitching
//		for each OS a sting is remembered, so OSswitching will bring back
//		last *.ics file (or just the default)
//		REMINDER_FOX_STORE_FILE  used to store all OS infos

function reminderFox_getReminderStoreFile() {
	
	var file = Components.classes["@mozilla.org/file/local;1"]
             .createInstance(Components.interfaces.nsILocalFile);
             
	// 1) setup the default location for "reminderfox.ics"	
   var defaultFile = Components.classes["@mozilla.org/file/directory_service;1"]
         .getService(Components.interfaces.nsIProperties)
         .get("ProfD", Components.interfaces.nsIFile);

   defaultFile.append( "reminderfox" );
   defaultFile.append( "reminderfox.ics" );		
   var defaultFilePath = defaultFile.path;

	// 2) get prefs storeFile.OS   -- saved file from different OSs
	var osTyp = rmFx_opSystemInfo();	// for new
	var osInfo = rmFx_opSystemInfo();	// for old
	var osFilePath = "";		
	var storeString = "";
	
   try {
      storeString = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_STORE_FILE);

		var fnd = storeString.indexOf("OS=" + osTyp + ":");
	   if (fnd > -1) {
			//for the current osTyp we have a 'storeFile', search it
			var osArray = storeString.split("OS=");
				for (var nOS=0; nOS < osArray.length; nOS++) {
					var cString = osArray[nOS];
					if (cString.substring(cString.length -1) == ",") {
						cString = cString.substring(0, cString.length-1);
					}
					fnd = cString.indexOf(osTyp + ":");
					if (fnd == 0) {
						var len = (osTyp + ":").length;
						storeString = cString.substring(len) ;
					}
				}
	   }
	} 	catch ( e ) {}
	   
	// check which file can be used
	//   1:  if fileinfo is valid, use it
	//   2:  else use OS setting, if not valid, use 'default'
	
	var savefilePathGO = "";
   // 1: check if 'osFilePath' is empty, use 'default'
   if (storeString == "" )  {
   	file.initWithPath(defaultFilePath);
   } else {
		try {	// 2: use fileinfo is valid
			savefilePathGO = storeString;
			file.initWithPath(savefilePathGO);
			file.exists();
		} catch (e) {  // 3: if failed, go with 'defaultFilePath'		
				savefilePathGO = "";
				file.initWithPath(defaultFilePath);
			}
		}
	// reminderFox_logMessageLevel("file.path : " + file.path, 2);
		
   return file;	   
}
//OSswitching    mods/adds  to support OS switching ---------- end ---		



	function reminderFox_getFileTimeStamp() {
		var file =   reminderFox_getReminderStoreFile();
	
	     // bail if the file doesn't yet exist; no reminders to read
	      if ( !file.exists() ) { 
	      	return -1;
	      }			
	
		var is = Components.classes["@mozilla.org/network/file-input-stream;1"]
			.createInstance( Components.interfaces.nsIFileInputStream );
		try {
			is.init( file,0x01, 00004, null);
		}
		catch ( e ) {
			reminderFox_logMessageLevel("Could not read reminder file: " + e.name  
					+  " -- " + e.message, REMINDER_FOX_LOG_LEVEL_INFO);
			return -1;
		}
		
		var scriptableStream = Components.classes["@mozilla.org/scriptableinputstream;1"]
		                                 .createInstance(Components.interfaces.nsIScriptableInputStream);
		scriptableStream.init(is);
		var chunk = scriptableStream.read(scriptableStream.available());		
		
		// maybe only read set # of bytes

		return reminderFox_getFileTimeStampFromString(chunk);
	}

	function reminderFox_getFileTimeStampFromString(chunk) {
		var index =	chunk.indexOf( REMINDERFOX_FILE_LAST_MODIFIED);
		if ( index != -1 ) {
			var newline = "\n";
			var returnLine = "\r";
			index = chunk.indexOf( ':', index );
			if ( index != -1 ) {
				var endIndex = chunk.indexOf( newline, index );
				var time = chunk.substring( index+1, endIndex );
				if ( time.charAt( time.length-1) == returnLine ) {
					time = time.substring( 0, time.length-1);
				}
				return reminderFox_trim(time);
			}
		}
		return -1;
	}

	function reminderFox_getReminderEvents() {
		if ( reminderFoxEvents == null ) {
			reminderFoxEvents = new Array();
			reminderFoxTodosArray = { };
			var file =   reminderFox_getReminderStoreFile();
	
	      // bail if the file doesn't yet exist; no reminders to read
	      if ( !file.exists() ) { 
	      	return reminderFoxEvents;
	      }			
		  reminderFox_readInRemindersAndTodosICSFromFile(reminderFoxEvents, reminderFoxTodosArray, file);
		}
		return reminderFoxEvents;
	}
	
	function reminderFox_getReminderTodos() {
		if ( reminderFoxTodosArray == null ) {
			reminderFoxEvents = new Array();
			reminderFoxTodosArray = { };
			var file = reminderFox_getReminderStoreFile();
	
	      // bail if the file doesn't yet exist; no reminders to read
	      if ( !file.exists() ) { 
	      	return reminderFoxTodosArray;
	      }			
		  reminderFox_readInRemindersAndTodosICSFromFile(reminderFoxEvents, reminderFoxTodosArray, file);
		}
		return reminderFoxTodosArray;
	}
	
	function reminderFox_clearRemindersAndTodos() {
		reminderFoxEvents = null;
		reminderFoxTodosArray = null;
	}
	
	function reminderFox_getRemindersById( id, reminders ) {
		if ( reminders == null ) {
			reminders = reminderFox_getReminderEvents();
		}
		for ( var i = 0; i < reminders.length; i++ ) {
			if ( reminders[i].id == id ) {
				return reminders[i];
			}
		}
		return null;
	}
	
	function reminderFox_getTodosById( id, todoList ) {
		if ( todoList != null ) { 
			for ( var i = 0; i < todoList.length; i++ ) {
				if ( todoList[i].id == id ) {
					return todoList[i];
				}
			}
		}
		return null;
	}
	
	function reminderFox_getSpecificTodoById( id ) {
		var i;
		var reminderFoxTodosArrayArg =  reminderFox_getReminderTodos();
		for ( var n in reminderFoxTodosArrayArg ) {
			var reminderTodos = reminderFoxTodosArrayArg[n];
			for (  i = 0; i < reminderTodos.length; i++ ) {		
				if ( reminderTodos[i].id == id ) {
					return reminderTodos[i];
				}
			}
		}
		return null;
	}
	
	

function reminderFox_isInteger(s) {  
	if ( s == null || s.length == 0 ) {
		return false;		
	}
	else {
	 	var i;
	    for (i = 0; i < s.length; i++) {   
	        // Check that current character is number.
	        var c = s.charAt(i);
	        if (((c < "0") || (c > "9"))) return false;
	    }
	    // All characters are numbers.
	    return true;
	}
}

function reminderFox_initiliazeTooltip() {
	var changed = reminderFox_ensureRemindersSynchronized();
	
	if ( !changed ) {
		// add some extra checks in when hiding tooltip; in case the setTimeout threads have been suspended, 
		// this will kick them off again if neccessary
		reminderFox_initializeReminderFoxHourly();
		
		
		//reminderFox_filesystemTimeStampHasChanged
		 
		 
	}
		
	reminderFox_logMessageLevel("Tooltip initialized: " + new Date(), REMINDER_FOX_LOG_LEVEL_FINE);
	
}

function reminderFox_hideTooltip() {
	reminderFox_showAlertSlider();
}

function reminderFox_ensureRemindersSynchronized() {
	var fileChanged = reminderFox_timeStampHasChanged();
	if ( fileChanged != -1 ) {
		var changed = false;
		try { 
			var waitForResponse = reminderFox_ensureRemoteRemindersSynchronized(true); 
			if ( !waitForResponse ) {
				changed = reminderFox_processRecentReminders(); 
			}
		}
		catch ( e ) {
		}		
		if ( changed ) {
			// write stuff out
			reminderFox_writeOutRemindersAndTodos(false);								
			reminderFox_syncWrittenChangesToRemote();		
		}
		else {
			reminderFox_storeTimeStamp(fileChanged);
		}
		
		var windowEnumerator =  reminderFox_getWindowEnumerator();
	
		if (windowEnumerator.hasMoreElements()) {
			var oldestWindow = windowEnumerator.getNext();		
			oldestWindow.reminderFox_updateRemindersInWindow();	
			reminderFox_clearRemindersAndTodos();

			while (windowEnumerator.hasMoreElements()) {
				var currentWindow = windowEnumerator.getNext();		
				currentWindow.reminderFox_updateRemindersInWindow();		
				currentWindow.reminderFox_clearRemindersAndTodos();						
			}
		}	
	}	
	
	 return fileChanged != -1;
}
	
/*
 * check the reminder description for any variables (eg: <1978>) that needs translating
 * 
 * My <1978> event == My 31st event
 * My <1978#> event == My 31 event
 * 
 * (maybe: 
 * My <1#> event == My 1 event  (increases each year)
 *   -- or <#1>  - but how would I know to increment each one?  
 */	
function reminderFox_processReminderDescription( reminder, year, isTodo ) {
	var index = reminder.summary.indexOf( "<" );
	if ( index != -1 ) {
		var endIndex = reminder.summary.indexOf( ">", index + 1 );
		if ( endIndex != -1 ) {
			var useYearOnly = false;
			var yearVal = reminder.summary.substring( index + 1, endIndex );
			if ( yearVal.length == 5 && yearVal.charAt(4) == '#' ) {
				yearVal = yearVal.substring(0,4);
				useYearOnly = true;
			}
			if ( yearVal.length == 4 ) {
				try {
					if (!reminderFox_isInteger(yearVal) ) {
						return reminder;
					}
					var yearInt = parseInt(yearVal );
					var currentYear = year;
					if ( currentYear == null ) {
						currentYear =  new Date().getFullYear();
					}
					
					var numOfYears = currentYear - yearInt;
					if ( numOfYears < 0 ) { 
						numOfYears = numOfYears * -1;   // convert negative years to positive
					}
					var numOfYearsStr = numOfYears + "";
					if ( !useYearOnly ) {
						if ( numOfYears > 0 && numOfYears < 32 ) {
							numOfYearsStr = reminderFox_getBundle().getString("rf.options.dateshort." +numOfYears +".name");
						}
						else {					
							var length = numOfYearsStr.length;
		
							if ( numOfYearsStr.lastIndexOf("11") != -1 && numOfYearsStr.lastIndexOf("11") == length -2 ) {
								numOfYearsStr =numOfYearsStr + reminderFox_getBundle().getString("rf.options.number.abbreviation.4");
							}
							else if ( numOfYearsStr.lastIndexOf("12") != -1 && numOfYearsStr.lastIndexOf("12") == length - 2 ) {
								numOfYearsStr =numOfYearsStr + reminderFox_getBundle().getString("rf.options.number.abbreviation.4");
							}
							else if (  numOfYearsStr.lastIndexOf("13") != -1 && numOfYearsStr.lastIndexOf("13") == length -2 ) {
								numOfYearsStr =numOfYearsStr + reminderFox_getBundle().getString("rf.options.number.abbreviation.4");
							}											
							else if (  numOfYearsStr.lastIndexOf("1") != -1 &&numOfYearsStr.lastIndexOf("1") == length - 1) {
								numOfYearsStr =numOfYearsStr + reminderFox_getBundle().getString("rf.options.number.abbreviation.1");
							}
							else if (numOfYearsStr.lastIndexOf("2") != -1 && numOfYearsStr.lastIndexOf("2") == length -1  ) {
								numOfYearsStr =numOfYearsStr + reminderFox_getBundle().getString("rf.options.number.abbreviation.2");
							}	
							else if ( numOfYearsStr.lastIndexOf("3") != -1 && numOfYearsStr.lastIndexOf("3") == length - 1 ) {
								numOfYearsStr =numOfYearsStr + reminderFox_getBundle().getString("rf.options.number.abbreviation.3");
							}	
							else {
								numOfYearsStr =numOfYearsStr + reminderFox_getBundle().getString("rf.options.number.abbreviation.4");
							}			
						}		
					}						
					
					var returnReminder;
					if ( isTodo  ) {  
						returnReminder = reminderFox_cloneReminderFoxTodo(reminder);
					}
					else {
						returnReminder = reminderFox_cloneReminderFoxEvent(reminder);
					}
					returnReminder.summary = returnReminder.summary.substring( 0, index ) + numOfYearsStr + 
						returnReminder.summary.substring( endIndex + 1 );
						
					// now we have the new description; re-run the process  in case there were multiple years	
					returnReminder = reminderFox_processReminderDescription(returnReminder, year, isTodo)
					return returnReminder;					
				}
				catch ( e ) {
				}
			}
		}
	}
	return reminder;
}	


function reminderFox_trim(s) {
	if ( s != null && s.length > 0 ) { 
		// Remove leading spaces and carriage returns
		while ((s.substring(0,1) == ' ') ) {
		 	s = s.substring(1,s.length); 
		 }
		
		// Remove trailing spaces and carriage returns
		while ((s.substring(s.length-1,s.length) == ' ') ) { 
			s = s.substring(0,s.length-1); 
		}
	}

	return s;
}

 
function reminderFox_constructReminderOutput(reminderEvents, reminderFoxTodosArrayArg, isExport, ignoreExtraInfo, postingMethod  ) {	
//	reminderFox_logMessageLevel("in reminderFox_constructReminderOutput", REMINDER_FOX_LOG_LEVEL_DEBUG);
//	if ( reminderEvents != null ) { 
//		reminderFox_logMessageLevel("reminderEvents.length: " + reminderEvents.length, REMINDER_FOX_LOG_LEVEL_DEBUG);
//	}
		
	var newline;
	if (navigator.appVersion.lastIndexOf('Win') != -1) {
		newline="\r\n";
	} else {
		newline="\n"
	}
	//var separator = newline + " :" ;
	var separator =  ":" ;
	
	var outputStr = "BEGIN:VCALENDAR" + newline;
	outputStr += "VERSION" + separator +  
							"2.0" + newline;
	outputStr += "PRODID" + separator + 
							 "-//ReminderFox V" + REMINDER_FOX_MIGRATED_PREF_VERSION +"//EN" + newline;
	var modifiedTime;
	
	// if exporting (via file or network), use existing timestamp
	 if ( isExport ) {
	 	modifiedTime = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_LAST_MODIFIED) + "";
	 }
	 else {	 		
	 	// otherwise, we're writing the file anew - set new current timestamp					 
		 reminderFox_lastModifiedTime = new Date().getTime();
		 modifiedTime = reminderFox_lastModifiedTime;
	}
	outputStr += REMINDERFOX_FILE_LAST_MODIFIED + separator + modifiedTime + newline;
	
	//postingMethod
	if (postingMethod == "" ||postingMethod == null || postingMethod == "PUBLISH") {	// for Invitation :  REQUEST						 
	outputStr += "METHOD" + separator +  
							"PUBLISH" + newline;}
		else {
			outputStr += "METHOD" + separator +  
							postingMethod + newline;
		}
		
		
	// output any preamble extra info (like timezones):
	if ( ignoreExtraInfo ) {
		// ignore extra fields
	}
	else if ( reminderFoxExtraInfoPrefix != null ) {
		var extraInfoArray = reminderFoxExtraInfoPrefix.split("\\n");		
		for ( var index = 0; index < extraInfoArray.length; index++ ) {
			var extraInfo = extraInfoArray[index];	
			outputStr += extraInfo + newline;				
		}	
	}

	// REMINDERS
	var reminder;
	for ( var i = 0; i < reminderEvents.length; i++ ) {
		reminder = reminderEvents[i];
		var summary = reminder.summary;
		outputStr += "BEGIN:VEVENT" +  newline;	
		outputStr += "UID" + separator +  reminder.id + newline;		
		
		//reminderFox_logMessageLevel("Writing out event: " + summary, REMINDER_FOX_LOG_LEVEL_DEBUG);		
		
		if ( summary != null ) {
			summary = reminderFox_EscapeCommas( summary );		
		}
		else { 
			summary = "";
		}					
		outputStr += reminderFox_foldLines( "SUMMARY" + separator +   summary , newline );			
		if ( isExport && ( reminder.extraInfo == null || reminder.extraInfo.indexOf( "CLASS" + separator) == -1 ) ) {
			outputStr += "CLASS" + separator +  "PUBLIC" + newline;												
		}						
														
		// set date
		var currentDate =  new Date( reminder.date.getFullYear(), reminder.date.getMonth(), reminder.date.getDate(), reminder.date.getHours(), reminder.date.getMinutes() );
		outputStr += reminderFox_createStringForDate( reminder, currentDate, isExport, separator, newline );
		
		var endDate = null;
		if ( reminder.endDate != null ) {
			endDate =  new Date( reminder.endDate.getFullYear(), reminder.endDate.getMonth(), reminder.endDate.getDate(), reminder.endDate.getHours(), reminder.endDate.getMinutes() );
		}
		outputStr += reminderFox_createStringForEndDate( reminder, endDate, isExport, separator, newline );
		
		if ( isExport && ( reminder.extraInfo == null || reminder.extraInfo.indexOf( "STATUS:") == -1 ) ) {
	 		outputStr += "STATUS:CONFIRMED" + newline;  				 	
	 	 }
			
		if ( reminder.notes != null ) {
			// replace actual new line  with newline characters
			var desc =reminder.notes.replace(new RegExp(/\n/g),"\\n");
			desc = reminderFox_EscapeCommas( desc );		
			outputStr +=  reminderFox_foldLines(  "DESCRIPTION" + separator + desc , newline );		
		}

		if (( reminder.categories != null ) && (reminder.categories != "")) {
			outputStr +=  reminderFox_foldLines( "CATEGORIES" + separator +  reminder.categories , newline );
		}
		
		outputStr += reminderFox_writeOutRecurrence(reminder, currentDate, separator, newline);	
		 
		if ( reminder.priority == REMINDER_PRIORITY_IMPORTANT) { 
			outputStr += "PRIORITY" + separator +  
									"1" + newline;				
		}

		if ( reminder.lastModified != null ) {
			outputStr += "LAST-MODIFIED" + separator +  reminder.lastModified + newline;			
		}
		
		if (reminder.remindUntilCompleted != REMINDERFOX_REMIND_UNTIL_COMPLETE_NONE) {
			outputStr += REMINDERFOX_EXTENDED + "REMIND-UNTIL-COMPLETED" + separator +  
									 reminder.remindUntilCompleted + newline;					
		}
		
		if ( reminder.location != null  && reminder.location != "") {
			var reminderLocation = reminderFox_EscapeCommas( reminder.location );		
			outputStr +=  reminderFox_foldLines( "LOCATION" + separator +  reminderLocation , newline );
		}
		if ( reminder.url != null && reminder.url != "") {
			outputStr +=  reminderFox_foldLines( "URL" + separator +  reminder.url , newline );
		}

		
		if ( reminder.completedDate != null ) {
			var year = reminder.completedDate.getFullYear();
			var month = reminder.completedDate.getMonth() +1;
			var day = reminder.completedDate.getDate();
			if (month < 10)
				month = "0" + month;
			if (day < 10)
				day = "0" + day;
			outputStr += REMINDERFOX_EXTENDED + "COMPLETED" + separator +  
										"" + year  + month  + day + newline;						
		}		
		
		if (reminder.messageID != null) {
			outputStr +=  reminderFox_foldLines( REMINDERFOX_EXTENDED + "MESSAGEID" + separator +  reminder.messageID, newline );							
		}	
		
		// write out extra info
		var dtstampFound = false;
		if ( reminder.extraInfo != null ) {
			// write out any extra info (inserted from other calendaring programs)
			var extraInfoArray = reminder.extraInfo.split("\\n");	
			for ( var index = 0; index < extraInfoArray.length; index++ ) {
				var extraInfo = extraInfoArray[index];	
				
				if ( extraInfo.indexOf( "DTSTAMP" ) != -1 ) {  
					dtstampFound = true;	
				}		
				else if ( extraInfo.indexOf( "COMMENT" ) != -1 ) {  
					extraInfo =extraInfo.replace(new RegExp(/\n/g),"\\n");
				}
				outputStr += reminderFox_foldLines( extraInfo, newline );	
			}	
		}
		// every event/todo must have a dtstamp; add it, if not there
		// 2009-02-16 -- if not '.lastModified'  then currenttime
		if ( !dtstampFound ) {
			if (!reminder.lastModified) {
				var currentDate = new Date(); 
				reminder.lastModified = reminderFox_getDateAsString(currentDate );
			}
			outputStr += "DTSTAMP" + separator +  reminder.lastModified + newline;			
		}
		
		if ( reminder.alarm != null ) {
			outputStr += "BEGIN:VALARM" + newline;	
			outputStr += "TRIGGER" + separator +  
									reminder.alarm + newline;
			outputStr += "ACTION" + separator +  "DISPLAY" + newline;			
			outputStr += reminderFox_foldLines( "DESCRIPTION" + separator +   summary , newline );		
			
			if ( reminder.alarmLastAcknowledge != null ) {
				outputStr +=REMINDERFOX_EXTENDED + "LASTACK" + separator + reminder.alarmLastAcknowledge + newline;	
			}			
			if ( reminder.snoozeTime != null ) {
				outputStr +=REMINDERFOX_EXTENDED + "SNOOZE-TIME" + separator + reminder.snoozeTime + newline;	
			}	
			
			
			outputStr += "END:VALARM" + newline;	
		}
				
		outputStr += "END:VEVENT" + newline
//		reminderFox_logMessageLevel("Finished writing event: " + summary, REMINDER_FOX_LOG_LEVEL_DEBUG);
	}

	
	// TODOs
	var todo;
	var dtstampStr = null;
	var tLen = 0;
	for ( var n in reminderFoxTodosArrayArg ) {
		var reminderTodos = reminderFoxTodosArrayArg[n];
		for (  i = 0; i < reminderTodos.length; i++ ) {
			todo = reminderTodos[i];
			outputStr += "BEGIN:VTODO" +  newline;	
			var summary = reminderFox_EscapeCommas( todo.summary );		
			if ( summary == null ) { 
				summary = "";
			} 
			outputStr +=  reminderFox_foldLines( "SUMMARY" + separator +  summary , newline );		
			outputStr +=  reminderFox_foldLines( "UID" + separator +  todo.id , newline );														
	
			if ( todo.date != null ) {
				var currentDate =  new Date( todo.date.getFullYear(), todo.date.getMonth(), todo.date.getDate(), todo.date.getHours(), todo.date.getMinutes() );
				outputStr += reminderFox_createStringForDate( todo, currentDate, isExport, separator, newline );
				
				if ( todo.endDate != null ) {
					var durationMillisecs =todo.endDate.getTime() - todo.date.getTime();
					var durationMins = durationMillisecs / ( 60 * 1000 );
					outputStr += "DURATION" + separator + "PT" + durationMins + "M" + newline;
				}
			}
			//currentDate.setMinutes( currentDate.getMinutes() + tzOffset );	// set this offset for UTC	
	
			if ( todo.notes != null ) {
				// replace actual new line  with newline characters
				var desc = todo.notes.replace(new RegExp(/\n/g),"\\n");
				desc = reminderFox_EscapeCommas( desc );	
				outputStr +=  reminderFox_foldLines( "DESCRIPTION" + separator +  desc , newline );		
			}
	
			if ( todo.priority == REMINDER_PRIORITY_IMPORTANT) { 
				outputStr += "PRIORITY" + separator +  "1" + newline;					
			}
			
			if (( todo.categories != null ) && (todo.categories != "")) {
				outputStr +=  reminderFox_foldLines( "CATEGORIES" + separator + todo.categories , newline );
			}

			outputStr += reminderFox_writeOutRecurrence(todo, currentDate, separator, newline);
			
			if ( todo.completedDate != null ) {
				var year = todo.completedDate.getFullYear();
				var month = todo.completedDate.getMonth() +1;
				var day = todo.completedDate.getDate();
				if (month < 10)
					month = "0" + month;
				if (day < 10)
					day = "0" + day;
				outputStr += "COMPLETED" + separator +  
											"" + year  + month  + day + "T" + "000000" +newline;						
			}				
			
					
			if (todo.showInTooltip) {
				outputStr += REMINDERFOX_EXTENDED + "SHOW-IN-TOOLTIP" + separator +  
										"1" + newline;		
			}
			
			if (todo.messageID != null) {
				outputStr +=  reminderFox_foldLines( REMINDERFOX_EXTENDED + "MESSAGEID" + separator +  todo.messageID , newline );							
			}			

// moved down after .extraInfo,  so a list name from extraInfo can be used		
//			if ( n != REMINDER_FOX_DEFAULT_TODOS_CATEGORY ) {
//				outputStr += REMINDERFOX_EXTENDED + "LISTID" + separator +  n  + newline;						
//			}					
				
			if ( todo.location != null  && todo.location != "") {
				var location = reminderFox_EscapeCommas( todo.location );	
				outputStr +=  reminderFox_foldLines( "LOCATION" + separator +  location, newline );
			}
			if ( todo.url != null && todo.url != "") {
				outputStr +=  reminderFox_foldLines( "URL" + separator +  todo.url , newline );
			}
				
		   var extraFound = false;
		   var dtstampFound = false;
			if ( todo.extraInfo != null ) {
				// write out any extra info (inserted from other calendaring programs)
				var extraInfoArray = todo.extraInfo.split("\\n");	
				for ( var index = 0; index < extraInfoArray.length; index++ ) {
					var extraInfo = extraInfoArray[index];	
					outputStr += reminderFox_foldLines( extraInfo, newline );	
					
					if ( extraInfo.indexOf( "DTSTAMP" ) != -1 ) {  
						dtstampFound = true;	
					}
					if ( extraInfo.indexOf( REMINDERFOX_EXTENDED + "LISTID" ) != -1 ) {  
						extraFound = true;	
					}		
				}	
			}		
		// every event/todo must have a dtstamp; add it, if not there
		// 2009-02-16 -- if not '.lastModified'  then currenttime
		if ( !dtstampFound ) {
		
			if (!todo.lastModified) { 
				var currentDate = new Date();
				todo.lastModified = reminderFox_getDateAsString(currentDate );
			}
			outputStr += "DTSTAMP" + separator +  todo.lastModified + newline;			
		}


// list name moved to here (after .extraInfo) 

		if (( n != REMINDER_FOX_DEFAULT_TODOS_CATEGORY ) && (extraFound == false)) {
			outputStr += REMINDERFOX_EXTENDED + "LISTID" + separator +  n  + newline;						
		}					


			
			if ( todo.alarm != null ) {
				outputStr += "BEGIN:VALARM" + newline;	
				outputStr += "TRIGGER" + separator +  todo.alarm + newline;
				outputStr += "ACTION" + separator +  "DISPLAY" + newline;			
				outputStr += reminderFox_foldLines( "DESCRIPTION" + separator +   summary, newline );	
				if ( todo.alarmLastAcknowledge != null ) {
					outputStr +=REMINDERFOX_EXTENDED + "LASTACK" + separator + todo.alarmLastAcknowledge + newline;	
				}		
				if ( todo.snoozeTime != null ) {
					outputStr +=REMINDERFOX_EXTENDED + "SNOOZE-TIME" + separator + todo.snoozeTime + newline;	
				}
		
				outputStr += "END:VALARM" + newline;	
			}									
						
			outputStr += "END:VTODO" +  newline;
			
			tLen++;		
		}
	}
	
	// write out any extra fields		
	if ( ignoreExtraInfo ) {
		// ignore extra fields
	}
	else if ( reminderFoxExtraInfo != null ) {
		var extraInfoArray = reminderFoxExtraInfo.split("\\n");		
		for ( var index = 0; index < extraInfoArray.length; index++ ) {
			var extraInfo = extraInfoArray[index];	
			outputStr += extraInfo + newline;				
		}	
	}
	
	//gW_backup&delete    add # of reminders
	var rLen = (reminderEvents != null) ? reminderEvents.length : 0;
	
	// outputStr += "X-REMINDERFOX-SUMMARY:Events=" + rLen + " Todos=" + tLen +  newline;
	
	outputStr += "END:VCALENDAR" +  newline;	
	
	//reminderFox_logMessageLevel("Finished output to file.  Final file:\n***************\n\n" + outputStr, REMINDER_FOX_LOG_LEVEL_DEBUG);	
	return outputStr;
}


function reminderFox_foldLines( line, newline ) {
	//  >>>>  break for long lines   RFC 2445 sec 4.1  
	var result = null;
	var LINE_LENGTH = 75;
	if ( line.length <= LINE_LENGTH ) {
		result = line + newline;
	} 
	else {
		result = line.substring( 0, LINE_LENGTH) + newline;
		var index = LINE_LENGTH;
		while ( (index + LINE_LENGTH)< line.length ) { 
			result = result + " " + line.substring( index, index + LINE_LENGTH-1 ) + newline;	  // -1, to account for prepended space
			index = index + LINE_LENGTH-1;
		}
		result = result + " " + line.substring( index, line.length ) + newline;;						
	}
	return result;
}

function reminderFox_createStringForDate( reminderOrTodo, currentDate, isExport, separator, newline ) {
		var outputStr;
		var year = currentDate.getFullYear();
		var month = currentDate.getMonth() +1;
		var day = currentDate.getDate();
		if (month < 10)
			month = "0" + month;
		if (day < 10)
			day = "0" + day;
		
		if ( reminderOrTodo.allDayEvent ) {
			outputStr = "DTSTART;VALUE=DATE" + separator +  
									"" + year  + month  + day + newline;				
		}
		else {
			var hours = currentDate.getHours();
			var minutes = currentDate.getMinutes();
			if (hours < 10)
				hours = "0" + hours;
			if (minutes < 10)
				minutes = "0" + minutes;

			outputStr = "DTSTART" + separator +  
									"" + year + month +  day + "T" + hours  + minutes + "00" + newline;				
								//	"" + year + month +  day + "T" + hours  + minutes + "00Z" + newline;					// add Z for UTC
		}
		return outputStr;
}


function reminderFox_createStringForEndDate( reminderOrTodo, currentDate, isExport, separator, newline ) {
	var nullDate = false;
	if ( currentDate == null ) {
		nullDate = true;
		currentDate = reminderOrTodo.date;
	}
	var outputStr = "";
	var year = currentDate.getFullYear();
	var month = currentDate.getMonth() +1;
	var day = currentDate.getDate();
	if (month < 10)
		month = "0" + month;
	if (day < 10)
		day = "0" + day;
	
	if ( reminderOrTodo.allDayEvent ) {
		if ( !nullDate ) {
			outputStr = "DTEND;VALUE=DATE" + separator +  
								"" + year  + month  + day + newline;				
		}
		else if ( isExport ) { 
			// if we are exporting reminders, then add the end-date for all day events because
			// some buggy clients don't understnand all-day events that have no end date even though
			// that is correct in the ICS spec
			currentDate.setDate( currentDate.getDate() + 1 );
			year = currentDate.getFullYear();
			month = currentDate.getMonth() +1;
			day = currentDate.getDate();
			if (month < 10)
				month = "0" + month;
			if (day < 10)
				day = "0" + day;				
			outputStr += "DTEND;VALUE=DATE" + separator +  
								"" + year  + month  + day + newline;						
		}																	
	}
	else {
		var hours = currentDate.getHours();
		var minutes = currentDate.getMinutes();
		if (hours < 10)
			hours = "0" + hours;
		if (minutes < 10)
			minutes = "0" + minutes;
		
		if ( !nullDate ) {
			outputStr = "DTEND" + separator +  
								"" + year + month +  day + "T" + hours  + minutes + "00" + newline;				
							//	"" + year + month +  day + "T" + hours  + minutes + "00Z" + newline;					// add Z for UTC
		}
		else if ( isExport ) { 
			currentDate.setHours( currentDate.getHours() + 1 );
			year = currentDate.getFullYear();
			month = currentDate.getMonth() +1;
			day = currentDate.getDate();
			if (month < 10)
				month = "0" + month;
			if (day < 10)
				day = "0" + day;							
			hours = currentDate.getHours();
			minutes = currentDate.getMinutes();
			if (hours < 10)
				hours = "0" + hours;
			if (minutes < 10)
				minutes = "0" + minutes;			
			outputStr += "DTEND" + separator +  
						"" + year + month +  day + "T" + hours  + minutes + "00" + newline;			
		}								
	}
	return outputStr;
}


function reminderFox_getDateAsString(  currentDate ) {
	var dateString = "";
	var year = currentDate.getFullYear();
	var month = currentDate.getMonth() +1;
	var day = currentDate.getDate();
	if (month < 10)
		month = "0" + month;
	if (day < 10)
		day = "0" + day;
		
	var hours = currentDate.getHours();
	var minutes = currentDate.getMinutes();
	var seconds = currentDate.getSeconds();
	if (hours < 10)
		hours = "0" + hours;
	if (minutes < 10)
		minutes = "0" + minutes;
	if (seconds < 10)
		seconds = "0" + seconds;		

	dateString= year +"" + month + "" +  "" +day + "T" + hours  + ""+ minutes + "" +seconds;		
	return dateString;
						// + "00Z" + newline;					// add Z for UTC
}

function reminderFox_getStringAsDate(  dateString ) {	
	if ( dateString != null && dateString.length > 0 ) {
		var date;
		var timeIndex = dateString.indexOf( "T" );
		var month = dateString.substring( 4,6);
		if ( month.indexOf( "0" ) == 0 ) {
			month = month.substring(1);
		}
		var monthInt = parseInt( month ) - 1;	
		// event with specific hourly time
		date = new Date( dateString.substring( 0, 4 ), monthInt,  dateString.substring( 6, 8 ) );
		date.setHours( dateString.substring( 9, 11 ), dateString.substring( 11, 13 ), dateString.substring( 13, 15) );
		
		// if event is stored in UTC time (20051208T224616Z), then take into accoutn UTC offset for the 
		// current time		
		reminderFox_adjustDateForTimeZones( dateString, dateString, date );
			
	}
	return date;
}

function reminderFox_writeOutRemindersAndTodos( isExport ) {	
	var outputStr = reminderFox_constructReminderOutput(reminderFox_getReminderEvents(), reminderFox_getReminderTodos(), isExport);  //  ALL  todos
	
	// now write file out to filesystem
	var file = reminderFox_getReminderStoreFile();
 
	if ( file.exists() == false ) {
		file.create( Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 420 );
	}

	reminderFox_writeStringToFile(outputStr, file, false);
	
	reminderFox_updateSunbirdCalendar();
}

/**
 * This function will update any remote calendars if usingSunbird or Lightning
 */
function reminderFox_updateSunbirdCalendar() { 
	if ( reminderFox_isSunbirdOrLightning() ) {		
		var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
	                       .getService(Components.interfaces.mozIJSSubScriptLoader);
		try { 
			// need to load sunbird/lightning javascript file that defines the 
			// getCompositeCalendar().refresh() call.  We do this via the subscript loader
			// because we can't directly include this .js file in the xul files since it is not 
			// available if using Firefox (or Thunderbird w/o Lightning, etc).
			loader.loadSubScript("chrome://calendar/content/calendar-management.js");
			getCompositeCalendar().refresh();
		}
		catch ( e ) { 
			//dump( "Exception: " + e.message );
		}
	}
}

function reminderFox_syncWrittenChangesToRemote() {
	// sync 'em up 
	var networkSync = REMINDER_FOX_NETWORK_SYNCHRONIZE_DEFAULT;		
	try {
		networkSync = reminderFox_prefs.getBoolPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_NETWORK_SYNCHRONIZE);
	} catch(e) {
	}	
	if ( networkSync ) {
		reminderFox_upload_Startup_headless(REMINDER_FOX_UI_MODE_HEADLESS_SHOW_ERRORS);
	}	
}

function reminderFox_uploadReminders() {
	var newOptions = { closeOnNoErrors: 1 };
	window.openDialog('chrome://reminderFox/content/network/upload.xul', 'reminderFox-upload', 'modal, centerscreen', newOptions);
}

function reminderFox_downloadReminders() {
	var newOptions = { closeOnNoErrors: 1 };
	window.openDialog('chrome://reminderFox/content/network/download.xul', 'reminderFox-download', 'modal,centerscreen', newOptions);
}

function reminderFox_writeStringToFile( outputStr, file, isExport ) {
	var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
		.createInstance( Components.interfaces.nsIFileOutputStream );
	outputStream.init( file, 0x04 | 0x08 | 0x20, 420, 0 );
	
	var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
	                          .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
	converter.charset = "UTF-8";
	
	var chunk = null;
	try {
		chunk = converter.ConvertFromUnicode(outputStr);
	}
	catch( e ) {
		chunk = outputStr;
	}
	outputStream.write(chunk, chunk.length);	
	
	 var fin = converter.Finish();
	 if (fin.length > 0)
	   outputStream.write(fin, fin.length);
	 outputStream.close();

	if ( !isExport && reminderFox_lastModifiedTime != null ) { 
		 reminderFox_storeTimeStamp(reminderFox_lastModifiedTime);
	}
}

function reminderFox_appendStringToFile( outputStr, file, isExport ) {
	var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
		.createInstance( Components.interfaces.nsIFileOutputStream );
	outputStream.init( file, 0x02 | 0x10, 420, 0 );
	
	var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
	                          .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
	converter.charset = "UTF-8";
	
	var chunk = null;
	try {
		chunk = converter.ConvertFromUnicode(outputStr);
	}
	catch( e ) {
		chunk = outputStr;
	}
	outputStream.write(chunk, chunk.length);	
	
	 var fin = converter.Finish();
	 if (fin.length > 0)
	   outputStream.write(fin, fin.length);
	 outputStream.close();

	if ( !isExport && reminderFox_lastModifiedTime != null ) { 
		 reminderFox_storeTimeStamp(reminderFox_lastModifiedTime);
	}
}

function reminderFox_storeTimeStamp(lastModified) {
	//var file = reminderFox_getReminderStoreFile();
	//var lastModified =  file.lastModifiedTime  
	reminderFox_prefsBranch.setCharPref(REMINDER_FOX_LAST_MODIFIED, 	lastModified);
	reminderFox_logMessageLevel("Store time stamp: " + new Date() + " -- " + lastModified, REMINDER_FOX_LOG_LEVEL_INFO);	 
}	

function reminderFox_timeStampHasChanged( ) {
	var timestamp = 	reminderFox_getFileTimeStamp()
	var lastRecordedTimeStamp = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_LAST_MODIFIED) + "";
//	currentTimeStamp =  file.lastModifiedTime;			
	var fileChanged = lastRecordedTimeStamp != timestamp;	
	reminderFox_logMessageLevel("TimeStamp Changed: " + new Date() + " - " + fileChanged + " --lastRecorded:" + lastRecordedTimeStamp + "--currentTimeStamp:" + timestamp +"-", REMINDER_FOX_LOG_LEVEL_INFO);	 
	
	if ( fileChanged ) {
		return timestamp;
	}
	else {
		return -1;
	}
}	

function reminderFox_filesystemTimeStampHasChanged( ) {
	//var timestamp = 	reminderFox_getFileTimeStamp()
	var lastRecordedTimeStamp = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_LAST_MODIFIED) + "";
	
	
	var file =   reminderFox_getReminderStoreFile();

     // bail if the file doesn't yet exist; no reminders to read
      if ( !file.exists() ) { 
      	return -1;
      }			
	var timestamp =  file.lastModifiedTime;			
	var fileChanged = lastRecordedTimeStamp != timestamp;	
	reminderFox_logMessageLevel("TimeStamp Changed: " + new Date() + " - " + fileChanged + " --lastRecorded:" + lastRecordedTimeStamp + "--currentTimeStamp:" + timestamp +"-", REMINDER_FOX_LOG_LEVEL_INFO);	 
	
	if ( fileChanged ) {
		return timestamp;
	}
	else {
		return -1;
	}
	
	// then do this...
	/*
	  var windowEnumerator =  reminderFox_getWindowEnumerator();
	
		if (windowEnumerator.hasMoreElements()) {
			var oldestWindow = windowEnumerator.getNext();		
			oldestWindow.reminderFox_updateRemindersInWindow();	
			reminderFox_clearRemindersAndTodos();

			while (windowEnumerator.hasMoreElements()) {
				var currentWindow = windowEnumerator.getNext();		
				currentWindow.reminderFox_updateRemindersInWindow();		
				currentWindow.reminderFox_clearRemindersAndTodos();						
			}
		}	
	 */

}

function reminderFox_getQuickAlarms( ) {	
	var quickAlarms = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + REMINDER_FOX_QUICK_ALARMS);		
	if ( quickAlarms != null && quickAlarms.length > 0  ) {
		
		var quickAlarmArray = null;
		if ( JSON ) { // FF3.5+
			quickAlarmArray = JSON.parse(quickAlarms);
		}
		else {
			var nativeJSON = Components.classes["@mozilla.org/dom/json;1"]
	    		.createInstance(Components.interfaces.nsIJSON);
			quickAlarmArray =nativeJSON.decode(quickAlarms);
		}
		
		return quickAlarmArray;
	}	
	else {
		return new Array();
	}
}


function reminderFox_updateQuickAlarmPref(quickAlarmArray) {
	var quickAlarms = null;
	if ( JSON ) { // FF3.5+
		quickAlarms = JSON.stringify(quickAlarmArray);
	}
	else {
		var nativeJSON = Components.classes["@mozilla.org/dom/json;1"]
    		.createInstance(Components.interfaces.nsIJSON);
		quickAlarms =nativeJSON.encode(quickAlarmArray);
	}
	
	reminderFox_setUnicodePref( REMINDER_FOX_QUICK_ALARMS, quickAlarms);	
	reminderFox_prefs.savePrefFile(null); 
}

function reminderFox_removeQuickAlarm( quickAlarmText ) {	
	var quickAlarmArray = reminderFox_getQuickAlarms();
	var indexToRemove = -1;
	for ( var i = 0; i < quickAlarmArray.length; i++ ) {
		if ( quickAlarmArray[i].text == quickAlarmText) {
			indexToRemove = i;
			break;
		}
	}
	
	if ( indexToRemove > -1 ) {
		reminderFox_removeElement( quickAlarmArray, indexToRemove );
		reminderFox_updateQuickAlarmPref( quickAlarmArray );
	}	
}

function reminderFox_getQuickAlarm( quickAlarmText ) {	
	var quickAlarmArray = reminderFox_getQuickAlarms();
	for ( var i = 0; i < quickAlarmArray.length; i++ ) {
		if ( quickAlarmArray[i].text == quickAlarmText) {
			return quickAlarmArray[i];
		}
	}
	return null;
	
}

function reminderFox_updateQuickAlarm( quickAlarm ) {	
	var quickAlarmArray = reminderFox_getQuickAlarms();
	var found = false;
	for ( var i = 0; i < quickAlarmArray.length; i++ ) {
		if ( quickAlarmArray[i].text == quickAlarm.text) {
			found = true;
			quickAlarmArray[i] = quickAlarm;
		}
	}
	
	if ( !found ) {
		quickAlarmArray[quickAlarmArray.length] = quickAlarm;
	}
	
	reminderFox_updateQuickAlarmPref(quickAlarmArray);
}


// split a string at newlines:   \n (Mac, *nix) or \r\n  (windows)  and unfold lines
function reminderFox_splitOnAllNewlinesAndUnfoldLines(input) {
	// just use common newline to read in lines - check for strings that end in \r (to handle windows \r\n)
	var newline = "\n";
	var returnLine = "\r";
	
	var remindersArray = input.split(newline);	
	var returnArray = new Array();	
	var returnArrayIndex = 0;
	for ( var index = 0; index < remindersArray.length; index++ ) {
		var readIn = remindersArray[index];	
		/* --------
		if (readIn.length > 0 &&  readIn.lastIndexOf(returnLine) == readIn.length -1 ) {
			readIn = readIn.substring(0, readIn.length -1 );
		} ---- */
		while (readIn.length > 0 &&  readIn.lastIndexOf(returnLine) == readIn.length -1 ) {
			readIn = readIn.substring(0, readIn.length -1 );
		}
		
		// handle line folding
		if (readIn.charAt(0) == ' ' && returnArrayIndex > 0 ) {  // if this line starts with a space, add it to the previous line
			returnArray[returnArrayIndex-1] += readIn.substring(1,readIn.length );
		}
		else {
			returnArray[returnArrayIndex] = readIn;
			returnArrayIndex++;
		}
	}	
	return returnArray;
}
function reminderFox_readInTimezone(reminderEvent, index, readIn, remindersArray) {
    var colonIndex;
    var timezoneId = null;
	var inStandard = false;
	
	var standardRRule = null;
	var daylightRRule = null;
	
	var standardRDate = null;
	var daylightRDate = null;
	
	var standardDateStart = null;
	var daylightDateStart = null;
	
	var standardOffsetFrom = null;
	var daylightOffsetFrom = null;
	
	var standardOffsetTo = null;
	var daylightOffsetTo= null;

	
	
	while ( index < remindersArray.length && readIn != "END:VTIMEZONE" ) {  
        if (reminderFoxExtraInfoPrefix == null) {
            reminderFoxExtraInfoPrefix = readIn;
         }
        else {
            if (reminderFoxExtraInfoPrefix.indexOf(readIn) == -1) { // ignore repeat elements
                reminderFoxExtraInfoPrefix = reminderFoxExtraInfoPrefix + "\\n" + readIn;
            }
         }

		if ( readIn.indexOf( "TZID" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			timezoneId = readIn.substring( colonIndex + 1);	
		}
		else if ( readIn.indexOf( "BEGIN:STANDARD" ) == 0 ) {
			inStandard = true;
		}
		else if ( readIn.indexOf( "END:STANDARD" ) == 0 ) {
			inStandard = false;
		}			
		else if ( readIn.indexOf( "RRULE" ) == 0 ) {
			if (inStandard) {
				standardRRule = readIn;
			}
			else {
				daylightRRule = readIn;
			}
		}	
		
		else if ( readIn.indexOf( "RDATE" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			if (inStandard) {
				standardRDate = readIn.substring(colonIndex + 1);
			}
			else {
				daylightRDate = readIn.substring(colonIndex + 1);
			}
		}
		else if ( readIn.indexOf( "DTSTART" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			if (inStandard) {
				standardDateStart = readIn.substring(colonIndex + 1);
			}
			else {
				daylightDateStart = readIn.substring(colonIndex + 1);
			}
		}
		
		else if ( readIn.indexOf( "TZOFFSETFROM" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			if (inStandard) {
				standardOffsetFrom = readIn.substring(colonIndex + 1);
			}
			else {
				daylightOffsetFrom = readIn.substring(colonIndex + 1);
			}
		}
		
		else if ( readIn.indexOf( "TZOFFSETTO" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			if (inStandard) {
				standardOffsetTo= readIn.substring(colonIndex + 1);
			}
			else {
				daylightOffsetTo = readIn.substring(colonIndex + 1);
			}
		}
		
		
			
		index++;
		readIn = remindersArray[index];
	}	
    
    if (reminderFoxExtraInfoPrefix == null) {
        reminderFoxExtraInfoPrefix = readIn;
    }
    else {
        if (reminderFoxExtraInfoPrefix.indexOf(readIn) == -1) { // ignore repeat elements
            reminderFoxExtraInfoPrefix = reminderFoxExtraInfoPrefix + "\\n" + readIn;
        }
    }
	
	// let's calculate
	
	var standardDate = null;
	// read in standard date
	if (standardRRule != null) {
		
		standardDate = reminderFox_calculateRRule(standardRRule);
		
		if (standardDateStart != null) {
			var standardDateStartDate = reminderFox_getDateTimeFromString( standardDateStart );
			standardDate.setHours( standardDateStartDate.getHours() );
			standardDate.setMinutes( standardDateStartDate.getMinutes() );
			standardDate.setSeconds( standardDateStartDate.getSeconds() );
		}
	}
	
	
	if (standardRDate != null) {
		// parsedate
		standardDate = reminderFox_getDateTimeFromString( standardRDate );
		// set to current year
		standardDate.setFullYear( new Date().getFullYear() );
	}
	
	var daylightDate = null;
	if (daylightRRule != null) {
		daylightDate = reminderFox_calculateRRule(daylightRRule);
		
		if (daylightDateStart != null) {
			var daylightDateStartDate = reminderFox_getDateTimeFromString( daylightDateStart );
			daylightDate.setHours( daylightDateStartDate.getHours() );
			daylightDate.setMinutes( daylightDateStartDate.getMinutes() );
			daylightDate.setSeconds( daylightDateStartDate.getSeconds() );
		}
	}
	
	if (daylightRDate != null) {
		// parsedate
		daylightDate = reminderFox_getDateTimeFromString( daylightRDate );
		// set to current year
		daylightDate.setFullYear( new Date().getFullYear() );
	}
	
	//dump( "\ntimezoneid: " + timezoneId + "\nSTANDARD:" + standardDate + "\n\ndaylight: " + daylightDate );
	var inDST = false;
	
	
	if (standardDate != null && daylightDate != null) {
		var today = new Date();
		var compare = reminderFox_compareDates(standardDate, daylightDate);
		if (compare == -1) {
			var compareToday = reminderFox_compareDates(today, standardDate);
			if (compareToday == -1) {			
				// we are in DST
				inDST = true;
			}
			else {
				compareToday = reminderFox_compareDates(today, daylightDate);
				if (compareToday == -1) {
					inDST = false;
				}
				else {
					inDST = true;
				}
			}						
		}
		else {
			var compareToday = reminderFox_compareDates(today, daylightDate);
			if (compareToday == -1) {
				inDST = false;
			}
			else {
				compareToday = reminderFox_compareDates(today, standardDate);
				if (compareToday == -1) {
					inDST = true;
				}
				else {
					inDST = true;
				}
			}
		}
	}
	
	
	
	var offset = null;
	if (inDST) {
		offset = daylightOffsetTo;
	}
	else {
		offset = standardOffsetTo; 
	}
	
	var negative = false;
	if (offset.charAt(0) == "-") {
		negative = true;
	}
	if (offset.charAt(0) == "-" || offset.charAt(0) == "+") {
		offset = offset.substring(1);
	}
	
	var hours = offset.substring( 0,2);
	var minutes = offset.substring( 2,4);
	var minutesOffset = parseInt( hours ) * 60;
	minutesOffset = minutesOffset + parseInt( minutes );
	
	if (negative) {
		minutesOffset = minutesOffset *-1;
	}
	
	timezoneId = reminderFox_trim( timezoneId.toUpperCase() );
	reminderFox_timezones[timezoneId] = minutesOffset;
	
	return index;
}

function reminderFox_getDateTimeFromString(eventDate){
			var date = null;
			var timeIndex = eventDate.indexOf( "T" );
			var month = eventDate.substring( 4,6);
			if ( month.indexOf( "0" ) == 0 ) {
				month = month.substring(1);
			}
			var monthInt = parseInt( month ) - 1;	
			if ( timeIndex == -1 ) {   
				// all day event
				date = new Date( eventDate.substring( 0, 4 ), monthInt, eventDate.substring( 6, 8) );	
			}
			else {
				// event with specific hourly time
				date = new Date( eventDate.substring( 0, 4 ), monthInt,  eventDate.substring( 6, 8 ) );
				
				var hoursInt = parseInt( eventDate.substring( 9, 11 ) );
				var minutsInt = parseInt( eventDate.substring( 11,13 ) );
				date.setHours( hoursInt );
				date.setMinutes( minutsInt );
			}
			return date;	
}


function reminderFox_calculateRRule(standardRRule){
	var reminderEvent = new ReminderFoxEvent(null, null, null);
	
	var date = new Date();
	date.setHours( 2 );
	date.setMinutes( 0 );
	date.setSeconds( 0 );
	var byDay = reminderFox_getRecurrenceByDay(standardRRule, true);
	var byMonth = reminderFox_getRecurrenceByMonth(standardRRule);
	date.setMonth(byMonth-1);
	
	var negativeIndex = byDay.indexOf("-");
	if (negativeIndex == -1) {
		var weekNum = byDay.substring(0, 1);
		var dayNum = reminderFox_getFirstDayValueFromByDay(byDay.substring(1));
		var standardDate = reminderFox_getDateForSpecifiedWeekNumber(date, dayNum, weekNum);
	}
	else {
		// subtract
		var byDay = reminderFox_getRecurrenceByDay(standardRRule, true);
		var byMonth = reminderFox_getRecurrenceByMonth(standardRRule);
		var weekNum = byDay.substring(1, 2);
		var dayNum = reminderFox_getFirstDayValueFromByDay(byDay.substring(2));
		
		var currentYear = date.getFullYear();
		if (reminderFox_isLeapYear(currentYear)) {
			dayArray = REMINDER_FOX_lDOMonth;
		}
		else {
			dayArray = REMINDER_FOX_DOMonth;
		}
		var numOfDaysInMonth = dayArray[byMonth-1];
		
		var totalDaysOfWeekInMonth = 5;
		var reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber(date, dayNum, 5);
		if (reminderWeekDateThisMonth > numOfDaysInMonth) {
			totalDaysOfWeekInMonth = 4;
		}
		totalDaysOfWeekInMonth = totalDaysOfWeekInMonth - weekNum + 1;
		
		standardDate = reminderFox_getDateForSpecifiedWeekNumber(date, dayNum, totalDaysOfWeekInMonth);
		
		
	}
	date.setDate( standardDate );
	return date;
}

function reminderFox_readInReminderEvent(reminderEvent, index, readIn, remindersArray) {
    var colonIndex;
    
	while ( index < remindersArray.length && readIn != "END:VEVENT" ) {
		if ( readIn.indexOf( "SUMMARY" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderEvent.summary = readIn.substring( colonIndex + 1);	
			reminderEvent.summary = reminderFox_unEscapeCommas( reminderEvent.summary );
		}
		else if ( readIn.indexOf( "DESCRIPTION" ) == 0 ) {
			 // there can be multiple notes DESCRIPTION fields; if we have already set the notes field,
			 // then we'll skip it if we encounter another one
			var skipNotes = reminderEvent.notes != null; 
				
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			if ( !skipNotes ) {
				reminderEvent.notes = readIn.substring( colonIndex + 1);	
			}
			
			// replace new line characters with actual newline
			reminderEvent.notes = reminderEvent.notes.replace(new RegExp(/\\n/g),"\n");
			reminderEvent.notes = reminderFox_unEscapeCommas( reminderEvent.notes );
			
			if ( reminderEvent.notes.length == 0 ) {
				reminderEvent.notes = null;  // dont' store empty notes
			}
		}		
		else 	if ( readIn.indexOf( "UID" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderEvent.id = readIn.substring( colonIndex + 1 );			
		}		
		else if ( readIn.indexOf( "LAST-MODIFIED" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderEvent.lastModified = readIn.substring( colonIndex + 1 );			
		}		
		else 	if ( readIn.indexOf( "PRIORITY" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderEvent.priority = readIn.substring( colonIndex + 1 );		
		}
		
		else 	if ( readIn.indexOf( "CATEGORIES" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			if (reminderEvent.categories == null) {
				reminderEvent.categories = readIn.substring( colonIndex + 1 );	
			} else {
				reminderEvent.categories += "," + readIn.substring( colonIndex + 1 );
			}	
		}
		
		else 	if ( readIn.indexOf( "LOCATION" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderEvent.location = readIn.substring( colonIndex + 1 );	
			reminderEvent.location = reminderFox_unEscapeCommas( reminderEvent.location );
		}
		else 	if ( readIn.indexOf( "URL" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderEvent.url = readIn.substring( colonIndex + 1 );	
		}
		else if ( readIn.indexOf( REMINDERFOX_EXTENDED + "REMIND-UNTIL-COMPLETED" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderEvent.remindUntilCompleted = readIn.substring( colonIndex + 1 );			
		}				
		else if ( readIn.indexOf( "BEGIN:VALARM" ) == 0 ) {
//			// we only want to process the first alarm, as there could be multiple alarm instances.
//			// We will ignore the others, and they will go into the extra info
//			var skipAlarms = false;
//			if ( reminderEvent.alarm != null && reminderEvent.alarm.length > 0 ) {
//				skipAlarms = true;
//			}
			// we only want to process the first alarm, as there could be multiple alarm instances.
			// We will ignore the others, and they will go into the extra info
			if ( reminderEvent.alarm == null || reminderEvent.alarm.length == 0 ) {
			
			index++;
			readIn = remindersArray[index];		
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			var alarmTime = readIn.substring( colonIndex + 1 );
			//if ( !skipAlarms ) {
				reminderEvent.alarm = alarmTime;
			//}
			
			// go to the end of VALARM (we don't want to pick up the DESCRIPTION field stored in the alarm
			while ( index < remindersArray.length && readIn != "END:VALARM" ) {
				index++;
				readIn = remindersArray[index];
							
				if ( readIn.indexOf( REMINDERFOX_EXTENDED + "LASTACK" ) == 0 ) {
					colonIndex = readIn.indexOf( ":" );
					while ( colonIndex == -1 ) {
						index++;
						readIn = remindersArray[index];
						colonIndex = readIn.indexOf( ":" );
					}					
					var alarmLastAcknowledge = readIn.substring( colonIndex + 1 );
				//	if ( !skipAlarms ) {
						reminderEvent.alarmLastAcknowledge = alarmLastAcknowledge;
					//}					
				}		
				if ( readIn.indexOf( REMINDERFOX_EXTENDED + "SNOOZE-TIME" ) == 0 ) {
					colonIndex = readIn.indexOf( ":" );
					while ( colonIndex == -1 ) {
						index++;
						readIn = remindersArray[index];
						colonIndex = readIn.indexOf( ":" );
					}					
					var snoozeTime = readIn.substring( colonIndex + 1 );
					//if ( !skipAlarms ) {
						reminderEvent.snoozeTime = snoozeTime;		
					//}			
				}			
				
				
			}
															
//			var alarmIndex1 = alarmTime.indexOf( "-PT" );
//			if ( alarmIndex1 != -1 ) {
//				var alarmIndex2 = alarmTime.indexOf( "M", alarmIndex1 );
//				if ( alarmIndex2 != -1 ) {
//					alarmTime = alarmTime.substring( alarmIndex1 + "-PT".length, alarmIndex2 );
//					reminderEvent.alarm = alarmTime;
//				}
//			}
}
		}	
		else if ( readIn.indexOf( REMINDERFOX_EXTENDED + "MESSAGEID" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderEvent.messageID = readIn.substring( colonIndex + 1 );			
		}	
		else if ( readIn.indexOf( "DTSTART" ) == 0 ||  readIn.indexOf( "DTEND" ) == 0 ) {
			var startDate = (readIn.indexOf( "DTSTART" ) == 0);
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			
			var eventDate = readIn.substring( colonIndex + 1 );			
			var timeIndex = readIn.indexOf( "T", colonIndex );
			var month = eventDate.substring( 4,6);
			if ( month.indexOf( "0" ) == 0 ) {
				month = month.substring(1);
			}
			var monthInt = parseInt( month ) - 1;	
			if ( timeIndex == -1 ) {   
				// all day event
				if ( startDate ) { 
					reminderEvent.date = new Date( eventDate.substring( 0, 4 ), monthInt, eventDate.substring( 6, 8) );	
				}
				else {
					reminderEvent.endDate = new Date( eventDate.substring( 0, 4 ), monthInt, eventDate.substring( 6, 8) );	
				}			
			}
			else {
				// event with specific hourly time
				if ( startDate ) {
					reminderEvent.date = new Date( eventDate.substring( 0, 4 ), monthInt,  eventDate.substring( 6, 8 ) );
					reminderEvent.date.setHours( eventDate.substring( 9, 11 ), eventDate.substring( 11, 13 ) );
					reminderFox_adjustDateForTimeZones( eventDate, readIn, reminderEvent.date );
					
					reminderEvent.allDayEvent = false;
				}
				else {
					reminderEvent.endDate = new Date( eventDate.substring( 0, 4 ), monthInt,  eventDate.substring( 6, 8 ) );
					reminderEvent.endDate.setHours( eventDate.substring( 9, 11 ), eventDate.substring( 11, 13 ) );
					reminderFox_adjustDateForTimeZones( eventDate, readIn, reminderEvent.endDate );
				}
			}
			if ( !startDate ) {
				// set the end date diff
				if ( reminderEvent.date != null && reminderEvent.endDate != null ) {
					reminderEvent.durationTime = reminderEvent.endDate.getTime() - reminderEvent.date.getTime();
				}
			}
		}
		else if ( readIn.indexOf( "DURATION" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			var duration = readIn.substring( colonIndex + 1 );		
			if ( reminderEvent.date != null ) {
				var durationMins = reminderFox_getDurationMinutes( duration );
				reminderEvent.durationTime = durationMins * 60 * 1000;  // set the end date diff
				reminderEvent.endDate = new Date( reminderEvent.date.getTime() + reminderEvent.durationTime );
			}
		}		
		else if ( readIn.indexOf( REMINDERFOX_EXTENDED + "COMPLETED" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			var eventDate = readIn.substring( colonIndex + 1 );			
			var month = eventDate.substring( 4,6);
			if ( month.indexOf( "0" ) == 0 ) {
				month = month.substring(1);
			}
			var monthInt = parseInt( month ) - 1;	
			reminderEvent.completedDate = new Date( eventDate.substring( 0, 4 ), monthInt, eventDate.substring( 6, 8) );				
		}	
		else if ( readIn.indexOf( "RRULE" ) == 0 ) {
			index = reminderFox_readInRecurrence( readIn, index, remindersArray, reminderEvent) ;			
		}	
		else if (  readIn != "BEGIN:VEVENT" ) {
			// this is a line that we do not recognize it.  Just store it
			if ( reminderEvent.extraInfo == null ) { 
				reminderEvent.extraInfo = readIn;						
			}
			else {
				// ignore repeat elements
				//gW  but import multiple ATTENDEE elements !!
				//   note: the element string may be equal up to the first LF
				
				if (( reminderEvent.extraInfo.indexOf( readIn ) == -1 ) || ( readIn.indexOf( "ATTENDEE" ) > -1 )) {
					// take care for LF in COMMENTs	
					if (readIn.indexOf( "COMMENT" ) == 0) {				
						readIn = readIn.replace(new RegExp(/\\n/g),"\n");
					}
					reminderEvent.extraInfo = reminderEvent.extraInfo + "\\n" + readIn;	
				}								
			}
		}	
	
		index++;
		readIn = remindersArray[index];
	}	
	
	return index;


}

/*
 * replace escaped commas with regular commas:
 * "Raleigh\, NC" --> "Raleigh, NC"
 */
function reminderFox_unEscapeCommas( stringValue ) {
	return stringValue.replace(/\\,/g,",");
}

/**
 * escape commas
 */
function reminderFox_EscapeCommas( stringValue ) {
	if ( stringValue == null ) { 
		return null;
	}
	
	return stringValue.replace(/,/g,"\\,")
}

function reminderFox_writeOutRecurrence(reminder, currentDate, separator, newline) {
		var endRepeatUntil = "";
		var outputStr = "";
		if ( reminder.recurrence.endDate != null ) {			
				//currentDate.setMinutes( currentDate.getMinutes() + tzOffset );	// set this offset for UTC	
			var year = reminder.recurrence.endDate.getFullYear();
			var endRepeatUntilmonth = reminder.recurrence.endDate.getMonth() +1;
			var day = reminder.recurrence.endDate.getDate();
			if (endRepeatUntilmonth < 10)
				endRepeatUntilmonth = "0" + endRepeatUntilmonth;
			if (day < 10)
				day = "0" + day;

			endRepeatUntil += ";UNTIL=" + "" + year  + endRepeatUntilmonth  + day;
		}	

		var interval = reminder.recurrence.interval;
		if ( interval == null || interval <= 1 ) {
			interval = 1;
		}
		if ( reminder.recurrence.type  == REMINDER_RECURRENCE_YEARLY ) {
			var month = currentDate.getMonth() +1;
			if (month < 10) {
				month = "0" + month;
			}		
			outputStr += "RRULE" + separator +  
									"FREQ=YEARLY;INTERVAL=" + interval + ";BYMONTH=" + month + endRepeatUntil + newline;				
		}
		else if ( reminder.recurrence.type  == REMINDER_RECURRENCE_YEARLY_DAY ) {
			var weekNumber = reminderFox_getWeekNumber( reminder.date );
			var month = currentDate.getMonth() +1;
			if (month < 10) {
				month = "0" + month;
			}
			outputStr += "RRULE" + separator +  
									"FREQ=YEARLY;INTERVAL=" + interval + ";BYMONTH=" + month +";BYDAY=" + weekNumber + reminderFox_weekday[reminder.date.getDay()] +endRepeatUntil + newline;					
		}		
		else 	if ( reminder.recurrence.type  == REMINDER_RECURRENCE_MONTHLY_DATE ) {
			outputStr += "RRULE" + separator +  
									 "FREQ=MONTHLY;INTERVAL=" + interval + endRepeatUntil +  newline;							
		}   
		else if ( reminder.recurrence.type  == REMINDER_RECURRENCE_MONTHLY_DAY ) {
			var weekNumber = reminderFox_getWeekNumber( reminder.date );
			outputStr += "RRULE" + separator +  
									 "FREQ=MONTHLY;INTERVAL=" + interval + ";BYDAY=" +  weekNumber + reminderFox_weekday[reminder.date.getDay()]+ endRepeatUntil + newline;	
		}
		else	if ( reminder.recurrence.type  == REMINDER_RECURRENCE_WEEKLY ) {		
			if ( reminder.recurrence.byDay == null || reminder.recurrence.byDay.length == 0) {
				outputStr += "RRULE" + separator +  
									"FREQ=WEEKLY;INTERVAL=" + interval + ";BYDAY=" + reminderFox_weekday[reminder.date.getDay()] + endRepeatUntil + newline;		
			}
			else {
				outputStr += "RRULE" + separator +  
									"FREQ=WEEKLY;INTERVAL=" + interval + ";BYDAY=" + reminder.recurrence.byDay + endRepeatUntil + newline;		
			}		
		}	
		else 	if ( reminder.recurrence.type  == REMINDER_RECURRENCE_DAILY ) {
			if ( interval > 1 ) {
				outputStr += "RRULE" + separator +  
									 "FREQ=DAILY;INTERVAL=" + interval +  endRepeatUntil + newline;	
			}
			else {
				outputStr += "RRULE" + separator +  
									 "FREQ=DAILY"+  endRepeatUntil + newline;	
			}		
											
		}    				
		else {		
			// no recurrence string for REMINDER_RECURRENCE_ONETIME
		}	
		return outputStr;
}

function reminderFox_getRecurrenceInterval( rrule ) {
	var interval = null;
	var intervalIndex =rrule.indexOf("INTERVAL=");
	try {
		if ( intervalIndex != -1 ) {	
			var semicolonIndex = rrule.indexOf( ";", intervalIndex);
			if ( semicolonIndex == -1 ) {
				interval = parseInt( rrule.substring( intervalIndex + "INTERVAL=".length, rrule.length ) );
			}
			else {
				interval = parseInt( rrule.substring( intervalIndex + "INTERVAL=".length, semicolonIndex ) )
			}
		}
	}
	catch ( e ) {		
	}
	return interval;
}

function reminderFox_getRecurrenceByDay( rrule, ignoreMultiples ) {
	var byday = "";
	var bydayIndex = rrule.indexOf("BYDAY=");
	try {
		if ( bydayIndex != -1 ) {	
			var semicolonIndex = rrule.indexOf( ";", bydayIndex);
			if ( semicolonIndex == -1 ) {
				byday = rrule.substring( bydayIndex + "BYDAY=".length, rrule.length );
			}
			else {
				byday = rrule.substring( bydayIndex + "BYDAY=".length, semicolonIndex );
			}
			if ( !ignoreMultiples && byday.indexOf( ",") == -1 ) { // only one byday; don't store it			
				byday = null;
			}
		}
	}
	catch ( e ) {		
	}

	return byday;
}

function reminderFox_getRecurrenceByMonth( rrule ) {
	var byday = "";
	var bydayIndex = rrule.indexOf("BYMONTH=");
	try {
		if ( bydayIndex != -1 ) {	
			var semicolonIndex = rrule.indexOf( ";", bydayIndex);
			if ( semicolonIndex == -1 ) {
				byday = rrule.substring( bydayIndex + "BYMONTH=".length, rrule.length );
			}
			else {
				byday = rrule.substring( bydayIndex + "BYMONTH=".length, semicolonIndex );
			}
		}
	}
	catch ( e ) {		
	}

	return byday;
}

function reminderFox_readInRecurrence( readIn, index, remindersArray, reminderEvent) {
	var colonIndex = readIn.indexOf( ":" );
	while ( colonIndex == -1 ) {
		index++;
		readIn = remindersArray[index];
		colonIndex = readIn.indexOf( ":" );
	}
	var rrule =  readIn.substring( colonIndex + 1 );
	if ( rrule.indexOf( "FREQ=YEARLY")  != -1  ) {				
		reminderEvent.recurrence.interval = reminderFox_getRecurrenceInterval( rrule );
		var byDayIndex = rrule.indexOf( "BYDAY=" );
		if ( byDayIndex != -1 ) {	
			// yearly on day
			reminderEvent.recurrence.type = REMINDER_RECURRENCE_YEARLY_DAY; 
		}
		else {			
			reminderEvent.recurrence.type = REMINDER_RECURRENCE_YEARLY;
		}
	}
	else 	if ( rrule.indexOf( "FREQ=MONTHLY" ) != -1  ) {
		var byDayIndex = rrule.indexOf( "BYDAY=" );
		if ( byDayIndex != -1 ) {	
			if ( rrule.indexOf( "INTERVAL=12") != -1  ) {	
				// yearly on day
				reminderEvent.recurrence.type = REMINDER_RECURRENCE_YEARLY_DAY; 
			}
			else {
				// monthly on day
				reminderEvent.recurrence.type = REMINDER_RECURRENCE_MONTHLY_DAY; 		
				reminderEvent.recurrence.interval = reminderFox_getRecurrenceInterval( rrule );			
			}
		}
		else {
			// monthly on date
			reminderEvent.recurrence.type = REMINDER_RECURRENCE_MONTHLY_DATE; 
			reminderEvent.recurrence.interval = reminderFox_getRecurrenceInterval( rrule );
		}
	}
	else 	if ( rrule.indexOf( "FREQ=WEEKLY")  != -1  ) {
		reminderEvent.recurrence.byDay = reminderFox_getRecurrenceByDay( rrule );
		reminderEvent.recurrence.type = REMINDER_RECURRENCE_WEEKLY;		
		reminderEvent.recurrence.interval = reminderFox_getRecurrenceInterval( rrule );			
	}
	else 	if ( rrule.indexOf( "FREQ=DAILY")  != -1  ) {
		reminderEvent.recurrence.type = REMINDER_RECURRENCE_DAILY;
		reminderEvent.recurrence.interval = reminderFox_getRecurrenceInterval( rrule );			
	}			
	
	// ;UNTIL=20060504T035959;INTERVAL=1
	var repeatUntil =  rrule.indexOf( "UNTIL=");
	if ( repeatUntil != -1 ) {
		 var endRepeatUntil =  rrule.indexOf( ";", repeatUntil);
		 if ( endRepeatUntil == -1 ) {
		 	endRepeatUntil = rrule.length;
		 }

		var repeatUntilStr = rrule.substring( repeatUntil + "UNTIL=".length, endRepeatUntil );
		var timeIndex = repeatUntilStr.indexOf( "T", colonIndex );
		var month = repeatUntilStr.substring( 4,6);
		if ( month.indexOf( "0" ) == 0 ) {
			month = month.substring(1);
		}
		var monthInt = parseInt( month ) - 1;
		if ( timeIndex == -1 ) {   
			// all day event
			reminderEvent.recurrence.endDate = new Date( repeatUntilStr.substring( 0, 4 ), monthInt, repeatUntilStr.substring( 6, 8) );
		}
		else {
			// event with specific hourly time
			reminderEvent.recurrence.endDate = new Date( repeatUntilStr.substring( 0, 4 ), monthInt,  repeatUntilStr.substring( 6, 8 ) );
			reminderEvent.recurrence.endDate.setHours( repeatUntilStr.substring( 9, 11 ), repeatUntilStr.substring( 11, 13 ) );
			
			reminderFox_adjustDateForTimeZones( repeatUntilStr, rrule, reminderEvent.recurrence.endDate );
		}
	}
	
	return index;
}



function reminderFox_readInReminderTodo(reminderTodo, index, readIn, remindersArray, reminderTodosArr) {
	var listID;  
	while ( index < remindersArray.length && readIn != "END:VTODO" ) {
		if ( readIn.indexOf( "SUMMARY" ) == 0 ) {
			var colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderTodo.summary = readIn.substring( colonIndex + 1);			
			reminderTodo.summary = reminderFox_unEscapeCommas( reminderTodo.summary );
		}
		else 	if ( readIn.indexOf( "UID" ) == 0 ) {
			var colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderTodo.id = readIn.substring( colonIndex + 1 );		
		}		
		else if ( readIn.indexOf( "DESCRIPTION" ) == 0 ) {
			var colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderTodo.notes = readIn.substring( colonIndex + 1);	

			// replace new line characters with actual newline
			reminderTodo.notes = reminderTodo.notes.replace(new RegExp(/\\n/g),"\n");		
			reminderTodo.notes = reminderFox_unEscapeCommas( reminderTodo.notes );
			
			if ( reminderTodo.notes.length == 0 ) {
				reminderTodo.notes = null;  // dont' store empty notes
			}
		}	

		else 	if ( readIn.indexOf( "CATEGORIES" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}			
			reminderTodo.categories = readIn.substring( colonIndex + 1 );	
		}
		
	else 	if ( readIn.indexOf( "LOCATION" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderTodo.location = readIn.substring( colonIndex + 1 );	
			reminderTodo.location = reminderFox_unEscapeCommas( reminderTodo.location );
		}
		else 	if ( readIn.indexOf( "URL" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderTodo.url = readIn.substring( colonIndex + 1 );	
		}
				
		else if ( readIn.indexOf( "PRIORITY" ) == 0 ) {
			var colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderTodo.priority = readIn.substring( colonIndex + 1 );		
		}			
		else if ( readIn.indexOf( "PERCENT-COMPLETE" ) == 0 ) {
			var colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			var completePercent = readIn.substring( colonIndex + 1 );		
			if ( completePercent == "100" ) {
				if ( reminderTodo.completedDate == null ) {
					reminderTodo.completedDate = new Date();
				}
			}
		}	
		else if ( readIn.indexOf( "RRULE" ) == 0 ) {
			index = reminderFox_readInRecurrence( readIn, index, remindersArray, reminderTodo) ;			
		}	
		else if ( readIn.indexOf( REMINDERFOX_EXTENDED + "SHOW-IN-TOOLTIP" ) == 0 ) {
			var colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderTodo.showInTooltip = readIn.substring( colonIndex + 1 );			
		}	
		else if ( readIn.indexOf( REMINDERFOX_EXTENDED + "MESSAGEID" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			reminderTodo.messageID = readIn.substring( colonIndex + 1 );			
		}	
		else if ( readIn.indexOf( REMINDERFOX_EXTENDED + "LISTID" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			listID = readIn.substring( colonIndex + 1 );			
		}	
		else if ( readIn.indexOf( "DTSTART" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			var eventDate = readIn.substring( colonIndex + 1 );			
			var timeIndex = readIn.indexOf( "T", colonIndex );
			var month = eventDate.substring( 4,6);
			if ( month.indexOf( "0" ) == 0 ) {
				month = month.substring(1);
			}
			var monthInt = parseInt( month ) - 1;	
			if ( timeIndex == -1 ) {   
				// all day event
				reminderTodo.date = new Date( eventDate.substring( 0, 4 ), monthInt, eventDate.substring( 6, 8) );		
			}
			else {
				// event with specific hourly time
				reminderTodo.date = new Date( eventDate.substring( 0, 4 ), monthInt,  eventDate.substring( 6, 8 ) );
				reminderTodo.date.setHours( eventDate.substring( 9, 11 ), eventDate.substring( 11, 13 ) );
				reminderFox_adjustDateForTimeZones( eventDate, readIn, reminderTodo.date );
				
				reminderTodo.allDayEvent = false;
			}
		}	
		else if ( readIn.indexOf( "DURATION" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			var duration = readIn.substring( colonIndex + 1 );		
			if ( reminderTodo.date != null ) {
				var durationMins = reminderFox_getDurationMinutes( duration );
				reminderTodo.durationTime = durationMins * 60 * 1000;  // set the end date diff
				reminderTodo.endDate = new Date( reminderTodo.date.getTime() + reminderTodo.durationTime );
			}
		}
		else if ( readIn.indexOf( "BEGIN:VALARM" ) == 0 ) {
			index++;
			readIn = remindersArray[index];	
			if (readIn != null && readIn.indexOf( "TRIGGER" ) == 0  ) {
				colonIndex = readIn.indexOf(":");
				while (colonIndex == -1) {
					index++;
					readIn = remindersArray[index];
					colonIndex = readIn.indexOf(":");
				}
				var alarmTime = readIn.substring(colonIndex + 1);
				reminderTodo.alarm = alarmTime;
			}
			
			// go to the end of VALARM (we don't want to pick up the DESCRIPTION field stored in the alarm
			while ( index < remindersArray.length && readIn != null && readIn != "END:VALARM" ) { 
				index++;
				readIn = remindersArray[index];
				if (readIn != null) {
					if (readIn.indexOf(REMINDERFOX_EXTENDED + "LASTACK") == 0) {
						colonIndex = readIn.indexOf(":");
						while (colonIndex == -1) {
							index++;
							readIn = remindersArray[index];
							colonIndex = readIn.indexOf(":");
						}
						var alarmLastAcknowledge = readIn.substring(colonIndex + 1);
						reminderTodo.alarmLastAcknowledge = alarmLastAcknowledge;
					}
					if (readIn.indexOf(REMINDERFOX_EXTENDED + "SNOOZE-TIME") == 0) {
						colonIndex = readIn.indexOf(":");
						while (colonIndex == -1) {
							index++;
							readIn = remindersArray[index];
							colonIndex = readIn.indexOf(":");
						}
						var snoozeTime = readIn.substring(colonIndex + 1);
						reminderTodo.snoozeTime = snoozeTime;
					}
				}		
															
			}									
		}			
		else if ( readIn.indexOf( "COMPLETED" ) == 0 ) {
			colonIndex = readIn.indexOf( ":" );
			while ( colonIndex == -1 ) {
				index++;
				readIn = remindersArray[index];
				colonIndex = readIn.indexOf( ":" );
			}
			var eventDate = readIn.substring( colonIndex + 1 );			
			var month = eventDate.substring( 4,6);
			if ( month.indexOf( "0" ) == 0 ) {
				month = month.substring(1);
			}
			var monthInt = parseInt( month ) - 1;	
			reminderTodo.completedDate = new Date( eventDate.substring( 0, 4 ), monthInt, eventDate.substring( 6, 8) );				

		}
		else if (  readIn != "BEGIN:VTODO" ) {
			// this is a line that we do not recognize it.  Just store it
			if ( reminderTodo.extraInfo == null ) {
				reminderTodo.extraInfo = readIn;					
			}
			else {
				if ( reminderTodo.extraInfo.indexOf( readIn ) == -1 ) {  // ignore repeat elements
					reminderTodo.extraInfo = reminderTodo.extraInfo + "\\n" + readIn;
				}
			}
		}						

		index++;
		readIn = remindersArray[index];
	}	


	// add todo to appropriate list	
	if ( listID == null ) {
		listID =REMINDER_FOX_DEFAULT_TODOS_CATEGORY;  
	}
	
	var todosArr =reminderTodosArr[listID];
	if ( todosArr == null ) {
		todosArr = new Array();
		reminderTodosArr[listID] = todosArr;
	}
	todosArr[todosArr.length] = reminderTodo;

	return index;
}


function reminderFox_getDurationMinutes( alarm ) {
		if ( alarm == null ) {
			return null;
		}
		// example: PT15M
		var alarmTime = alarm;
		var result = null;						 
		var alarmIndex1 = alarmTime.indexOf( "PT" );
		if ( alarmIndex1 != -1 ) {
			var alarmIndex2 = alarmTime.indexOf( "M", alarmIndex1 );
			if ( alarmIndex2 != -1 ) {
				alarmTime = alarmTime.substring( alarmIndex1 + "PT".length, alarmIndex2 );		
				result = parseInt( alarmTime );	
			}
			else {
				alarmIndex2 = alarmTime.indexOf( "H", alarmIndex1 );
				if ( alarmIndex2 != -1 ) {
					alarmTime = alarmTime.substring( alarmIndex1 + "PT".length, alarmIndex2 );		
					result = parseInt(alarmTime) * 60;
				}	
			}	
		}
		else {
			alarmIndex1 = alarmTime.indexOf( "P" );
			if ( alarmIndex1 != -1 ) {
				var alarmIndex2 = alarmTime.indexOf( "D", alarmIndex1 );
				if ( alarmIndex2 != -1 ) {
					alarmTime = alarmTime.substring( alarmIndex1 + "P".length, alarmIndex2 );		
					result = parseInt( alarmTime ) * 24 * 60;					
				}
			}
		}		
		return result;				 
}

function reminderFox_isCompletedForDate( reminder, reminderInstanceDate ) {
	if ( reminder.completedDate == null ) {
		return false;
	}
	
	 // if this is a one-time reminder that has been marked complete at any date, then it is completed
	if ( reminder.recurrence.type == REMINDER_RECURRENCE_ONETIME ) { 
		return true;
	}
	
	
	// return completed (true) if marked complete and the date is less than or equal to the reminder's date
	if ( reminderFox_compareDates(reminderInstanceDate, reminder.completedDate ) == 1 ) {
		return false;
	}
	else {
		return true;
	}
}

function reminderFox_readInRemindersAndTodosICSFromFile(reminderEvents, reminderTodos, file, ignoreExtraInfo) {
	var is = Components.classes["@mozilla.org/network/file-input-stream;1"]
		.createInstance( Components.interfaces.nsIFileInputStream );
	try {
		is.init( file,0x01, 00004, null);
	}
	catch ( e ) {
		reminderFox_logMessageLevel("Could not read reminder file: " + e.name  +  " -- " + e.message, REMINDER_FOX_LOG_LEVEL_INFO);
		return;
	}

	reminderFox_readInRemindersAndTodosICSFromStream(reminderEvents, reminderTodos, is, ignoreExtraInfo);
}

/* Called also from download.js */
function reminderFox_readInRemindersAndTodosICSFromStream(reminderEvents, reminderTodosArr, is, ignoreExtraInfo) {	
	var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
	                          .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
	converter.charset = /* The character encoding you want, using UTF-8 here */ "UTF-8";
	
	// Now, read from the stream
	var scriptableStream = Components.classes["@mozilla.org/scriptableinputstream;1"]
	                                 .createInstance(Components.interfaces.nsIScriptableInputStream);
	scriptableStream.init(is);
	var chunk = scriptableStream.read(scriptableStream.available());
	var input = null;
	try {
		 input = converter.ConvertToUnicode(chunk);
	}
	catch( e ) {
		// if the conversion fails (say importing from a previous version before the conversion code was in place)
		// then just set the input to the read-in value
		input = chunk;
	}		

	reminderFox_readInRemindersAndTodosICSFromString(reminderEvents, reminderTodosArr, input, ignoreExtraInfo );
}



function reminderFox_readInRemindersAndTodosICSFromString(reminderEvents, reminderTodosArr, input, ignoreExtraInfo) {
	var remindersArray;
	var reminderEventsIndex = 0;
	var i, j;
	// if reading from a source that could be from a different OS (usually on import), 
	// then check the newlines as they could differ from the current OS
	//if ( checkNewlines ) {
	// actually..  if sharing the stored reminders location between windows/linux or sharing remotely, 
	// we need to check the newlines everytime
	remindersArray = reminderFox_splitOnAllNewlinesAndUnfoldLines(input);

	var index = 0;
	var readIn = remindersArray[index];
	// bypass header 
	//gW_iCal     modified to get the METHOD to  reminderfox_Method
	reminderfox_Method="";
	
	while ( index < remindersArray.length  ) {


		if (readIn == "BEGIN:VTIMEZONE") {
			// calculate list of timezones and current offset 
			var reminderEvent2 = new ReminderFoxEvent( null, null, null );
			reminderEvent2.recurrence.type = REMINDER_RECURRENCE_ONETIME;
			index = reminderFox_readInTimezone( reminderEvent, index, readIn, remindersArray);
		}
		else if ( readIn.indexOf( "METHOD:" )  == 0)  {                        
	       	reminderfox_Method = readIn.substring("METHOD:".length).toUpperCase();
	    }
		else if ( readIn == "BEGIN:VEVENT" ) {
			var reminderEvent = new ReminderFoxEvent( null, null, null );
			reminderEvent.recurrence.type = REMINDER_RECURRENCE_ONETIME;
			index = reminderFox_readInReminderEvent( reminderEvent, index, readIn, remindersArray);
			reminderEvents[reminderEventsIndex] = reminderEvent;
			reminderEventsIndex++;
		}
		else if ( readIn == "BEGIN:VTODO" ) {
			var reminderTodo = new ReminderFoxTodo( null, null );
			index = reminderFox_readInReminderTodo( reminderTodo, index, readIn, remindersArray, reminderTodosArr);					
		}	
		else if ( readIn.length > 0 && 
			 readIn.indexOf( "VCALENDAR" )  == -1  &&
			 readIn.indexOf( "VERSION" )  == -1  &&
			 readIn.indexOf( "PRODID" )  == -1  &&
			 readIn.indexOf( "METHOD" )  == -1  &&
			 readIn.indexOf( "REMINDERFOX" )  == -1 ) {
			// if doesn't equal any known reminderfox fields, store it
			if ( ignoreExtraInfo ) {
				// if we don't care about extra info, don't store it
			}
			else { 
				if ( reminderFoxExtraInfo== null ) {
					reminderFoxExtraInfo = readIn;		
				}
				else {
					if ( reminderFoxExtraInfo.indexOf( readIn ) == -1 ) {  // ignore repeat elements
						reminderFoxExtraInfo =reminderFoxExtraInfo + "\\n" + readIn;
					}				
				}	
			}	
		}		
		index++;
		readIn = remindersArray[index];
	}
}

function reminderFox_readInFileContents(file) {
	var is = Components.classes["@mozilla.org/network/file-input-stream;1"]
		.createInstance( Components.interfaces.nsIFileInputStream );
	try {
		is.init( file,0x01, 00004, null);
	}
	catch ( e ) {
		reminderFox_logMessageLevel("Could not read reminder file: " + e.name  +  " -- " + e.message, REMINDER_FOX_LOG_LEVEL_INFO);
		return null;
	}
	
	
	var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
	                          .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
	converter.charset = /* The character encoding you want, using UTF-8 here */ "UTF-8";
	
	// Now, read from the stream
	var scriptableStream = Components.classes["@mozilla.org/scriptableinputstream;1"]
	                                 .createInstance(Components.interfaces.nsIScriptableInputStream);
	scriptableStream.init(is);
	var chunk = scriptableStream.read(scriptableStream.available());
	var input = null;
	try {
		 input = converter.ConvertToUnicode(chunk);
	}
	catch( e ) {
		// if the conversion fails (say importing from a previous version before the conversion code was in place)
		// then just set the input to the read-in value
		input = chunk;
	}		
	
	return input;
}


function reminderFox_mergeEvents( existingEvents, importedEvents ) {
	var i;  var existNo = 0; var importNo = 0;
	for ( i = 0; i < importedEvents.length; i++ ) {
		var exists = reminderFox_eventExists( existingEvents, importedEvents[i] );
		if ( !exists ) {
			// add reminder in sorted order...
			var sortedIndex = reminderFox_getSortedIndexOfNewReminder( existingEvents, importedEvents[i], false );
			reminderFox_insertIntoArray( existingEvents,  importedEvents[i], sortedIndex );
			importNo++;
		} else {
			existNo++;
		}
	}
	return { importNo:importNo , existNo:existNo};

}

function reminderFox_mergeTodos( existingTodosArray, importedTodosArray ) {	
	var i; var existNo = 0; var importNo = 0;
	for ( var n in importedTodosArray ) {
		var importedTodos = importedTodosArray[n];
		var existingTodos = existingTodosArray[n];
		
		if ( existingTodos == null ) {
			existingTodos = new Array();
			existingTodosArray[n] = existingTodos;
			for ( i = 0; i < importedTodos.length; i++ ) {
				var sortedIndex = reminderFox_getSortedIndexOfNewTodo( existingTodos, importedTodos[i] );
				reminderFox_insertIntoArray( existingTodos,  importedTodos[i], sortedIndex );
				importNo++;
			}	
		}
		else {
			for ( i = 0; i < importedTodos.length; i++ ) {
				var exists = reminderFox_eventExists( existingTodos, importedTodos[i] );
				if ( !exists ) {
					// add todo in sorted order...
					var sortedIndex = reminderFox_getSortedIndexOfNewTodo( existingTodos, importedTodos[i] );
					reminderFox_insertIntoArray( existingTodos,  importedTodos[i], sortedIndex );
					importNo++;
				} else {
					existNo++;
				}
			}
		}
	}		
	return {importNo:importNo , existNo:existNo};
}

function reminderFox_eventExists( existingEvents, importedEvent ) {
		for ( var i = 0; i < existingEvents.length; i++ ) {
			if ( existingEvents[i].id == importedEvent.id ) {
				return true;
			}
		}
		return false;
}

function reminderFox_importRemindersUpdateAll( isNetworkImport, lastModifiedTime) {	
	if ( lastModifiedTime != null ) {
		reminderFox_lastModifiedTime = lastModifiedTime;
		reminderFox_storeTimeStamp(reminderFox_lastModifiedTime);
	}

	var outputStr = reminderFox_constructReminderOutput(reminderFoxEvents, reminderFoxTodosArray, isNetworkImport);
	
	// now write file out to filesystem
	var file =   reminderFox_getReminderStoreFile();
	if ( file.exists() == false ) {
		file.create( Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 420 );
	}

	reminderFox_writeStringToFile(outputStr, file, false);

	// update all windows with imported reminders
	try {
		var windowEnumerator =  reminderFox_getWindowEnumerator();
	
		// update all of the browsers
		while (windowEnumerator.hasMoreElements()) {
			var currentWindow = windowEnumerator.getNext();		
			currentWindow.reminderFoxEvents = reminderFoxEvents;
			currentWindow.reminderFoxTodosArray  = reminderFoxTodosArray;

			currentWindow.reminderFox_updateRemindersInWindow();			
			currentWindow.reminderFox_clearRemindersAndTodos();
		}
	}
	catch(e) {
	}
	
      
}





function reminderFox_optionsPopulateYearList( currentDate ) {
	var todaysDate = new Date();
	// start with last year , in case they want to create a repeating reminder
	// from a previous month
	var year = parseInt(todaysDate.getFullYear()) -1;   

	var yearlist = document.getElementById('yearlist');
	while ( yearlist.firstChild.hasChildNodes()) {
	      yearlist.firstChild.removeChild( yearlist.firstChild.firstChild);
	}	

 	for ( var k = 0; k < 5; k++ ) {
		var newYear = document.createElement("menuitem");
		var yearVal = year + k;
		newYear.setAttribute("label", yearVal);
		yearlist.firstChild.appendChild(newYear);
	}
	
	yearlist.label = currentDate.getFullYear();
}


function reminderFox_optionsPopulateDateList( currentDate) {
	var year = parseInt(currentDate.getFullYear());
	var daylist = document.getElementById('daylist');
	var items = daylist.firstChild.childNodes;
	// remove ending nodes that could possibly be different each month
	// (i.e. any date greater than 28)
	var length = daylist.firstChild.childNodes.length - 1;	
	for ( var j = length; j >= 28; j-- ) {
		daylist.firstChild.removeChild( items[j] );
	}

	// now add proper # of days for this month
	var dayArray;
	if (reminderFox_isLeapYear(parseInt(year))) {
		dayArray = REMINDER_FOX_lDOMonth;
	}
	else {
		dayArray = REMINDER_FOX_DOMonth;
	}

	var monthlist = document.getElementById('monthlist');
	var currentMonth = monthlist.selectedIndex;

	var numOfDays = dayArray[currentMonth];
 	for ( var k = 29; k < numOfDays + 1; k++ ) {
		var newDay = document.createElement("menuitem");
		var str = k + "";
		newDay.setAttribute("label", str);
		daylist.firstChild.appendChild(newDay);
	}
	

	// now make sure the dateList is not showing a date greater than
	// the number of days in the selected month; if it is set the list
	// to show the last day of the month
	var dayname = parseInt(daylist.label);

	var numOfDaysInt = parseInt( numOfDays );
	if ( dayname > numOfDaysInt ) {
		daylist.selectedItem = daylist.firstChild.childNodes[numOfDaysInt - 1];
	}		
}

function reminderFox_getDateVariable( reminder, date, variableDateString )  {
	var reminderLabel = variableDateString;
	
	// Replace the [variables]	
	var startBracketIndex =reminderLabel.indexOf("[");
	while (startBracketIndex != -1) {
		var endBracketIndex = reminderLabel.indexOf("]", startBracketIndex);
		if (endBracketIndex != -1) {
			// Check for a fishy [
			if (endBracketIndex - startBracketIndex < 3) {
				startBracketIndex = reminderLabel.indexOf("[", ++startBracketIndex);
			}
			else {
				var variable = reminderLabel.substring(startBracketIndex + 1, endBracketIndex);		
				var decodedVariable = reminderFox_decodeReminderLabelVariable(reminder, variable, date);
				var decodedVariableLength = decodedVariable.length;
				var startTrim = startBracketIndex;
				var endTrim = endBracketIndex;
				if ( variable == "time" && decodedVariableLength == 0 ) {
					// trim the ( ) from around time if the time is empty (all-day event)
					if ( reminderLabel.charAt( startBracketIndex - 1 ) == "(" &&
						reminderLabel.charAt( endBracketIndex + 1 ) == ")"  ) {
						startTrim = startTrim - 1;
						endTrim = endTrim + 1;
					}
				}
				reminderLabel = reminderLabel.substring(0, startTrim) + decodedVariable + reminderLabel.substring(endTrim + 1, reminderLabel.length);
				startBracketIndex = reminderLabel.indexOf("[", startBracketIndex + decodedVariableLength);
			}
		}
	}
	
	return reminderLabel;
}



function reminderFox_optionsSetNewReminderDate( date, repopulateDays ) {
	var month = date.getMonth();
	var day = date.getDate() - 1; // account for 1-offset	
	var monthlist = document.getElementById('monthlist');

	var items = monthlist.firstChild.childNodes;
    monthlist.selectedItem = items[month];
    
	// if month or year has changed, we want to reseed the date drop-down list with the appropriate
	// number of days for that month
    if ( repopulateDays ) {
   		reminderFox_optionsPopulateDateList(date);
   	}
    
	var dayList = document.getElementById('daylist');
	items = dayList.firstChild.childNodes;
    dayList.selectedItem = items[day];	
}



/* SORTING */
function reminderFox_sortArraySwap( array, a, b )
{
	var tmp=array[a];
	array[a]=array[b];
	array[b]=tmp;
}


function reminderFox_compareColumnReminder1LessThanDate( reminder1, reminder2 ) {
	if ( reminder1.date == null && reminder2.date != null ) {
		return false
	}
	if ( reminder1.date != null && reminder2.date == null ) {
		return true
	}
	if ( reminder1.date == null && reminder2.date == null ) {
		return reminder1.originalIndex < reminder2.originalIndex;
	}	
	
	// otherwise, they both have dates - compare them
	var compare = reminderFox_compareReminderDatesAndTimes( reminder1, reminder2 );
	if ( compare == -1 ) { 
		return true;
	}
	else if ( compare == 1 ){
		return false;
	}	
	else {		
		return reminder1.originalIndex < reminder2.originalIndex;
	}
}

function reminderFox_compareColumnReminder1LessThanReminderCompletedDate( reminder1, reminder2 ) {	
	var completed1 = reminderFox_isCompletedForDate( reminder1, reminder1.date );
	var completed2 = reminderFox_isCompletedForDate( reminder2, reminder2.date );
		
	if ( !completed1 && completed2 ) {
		return false;
	}
	else if ( completed1 && !completed2 ) {
		return true;
	}
	else if ( !completed1 && !completed2 ) {
		return reminder1.originalIndex < reminder2.originalIndex;
	}
	
	// otherwise, they both have completed dates - compare them
	var compare = reminderFox_compareDates( reminder1.completedDate, reminder2.completedDate );	
	if ( compare == -1 ) { 
		return true;
	}
	else if ( compare == 1 ){
		return false;
	}	
	else {
		return reminder1.originalIndex < reminder2.originalIndex;
	}	
}

function reminderFox_compareColumnReminder1LessThanReminderEndDate( reminder1, reminder2 ) {	
	if ( reminder1.endDate == null && reminder2.endDate != null ) {
		return false
	}
	if ( reminder1.endDate != null && reminder2.endDate == null ) {
		return true
	}
	if ( reminder1.endDate == null && reminder2.endDate == null ) {
		return reminder1.originalIndex < reminder2.originalIndex;
	}	
	
	var myEndDate1 = new Date( reminder1.date.getTime() + reminder1.durationTime );
	if ( reminder1.allDayEvent ) {
		myEndDate1.setDate( myEndDate1.getDate() -1 ); // all-day offset
	}

	var myEndDate2 = new Date( reminder2.date.getTime() + reminder2.durationTime );
	if ( reminder2.allDayEvent ) {
		myEndDate2.setDate( myEndDate2.getDate() -1 ); // all-day offset
	}
	
	// otherwise, they both have dates - compare them
	var compare = reminderFox_compareReminderDatesAndTimes( reminder1, reminder2, myEndDate1, myEndDate2 );
	if ( compare == -1 ) { 
		return true;
	}
	else if ( compare == 1 ){
		return false;
	}	
	else {
		return reminder1.originalIndex < reminder2.originalIndex;
	}
	
}
	

function reminderFox_compareColumnReminder1LessThanCompletedDate( reminder1, reminder2 ) {	
	if ( reminder1.completedDate == null && reminder2.completedDate != null ) {		
		return false;
	}
	else if ( reminder1.completedDate != null && reminder2.completedDate == null ) {
		return true;
	}
	else if ( reminder1.completedDate == null && reminder2.completedDate == null ) {
		return reminder1.originalIndex < reminder2.originalIndex;
	}
	
	// otherwise, they both have completed dates - compare them
	var compare = reminderFox_compareDates( reminder1.completedDate, reminder2.completedDate );
	if ( compare == -1 ) { 
		return true;
	}
	else if ( compare == 1 ){
		return false;
	}	
	else {
		return reminder1.originalIndex < reminder2.originalIndex;
	}
	
}

function reminderFox_compareColumnReminder1LessThanSummary( reminder1, reminder2 ) {
	return reminder1.summary.toLowerCase() < reminder2.summary.toLowerCase();
}

function reminderFox_compareColumnReminder1LessThanCategory( reminder1, reminder2 ) {
	if (  reminder1.categories == null  && reminder2.categories == null ) {
		return reminder1.originalIndex < reminder2.originalIndex;
	} 
	else if ( reminder1.categories == null  && reminder2.categories != null ) { 
		return false;
	}
	else 	if ( reminder1.categories != null  && reminder2.categories == null ) { 
		return true;
	}
	else if ( reminder1.categories.toLowerCase() ==  reminder2.categories.toLowerCase()  ) {
		return reminder1.originalIndex < reminder2.originalIndex;
	}
	else {
		return reminder1.categories.toLowerCase() < reminder2.categories.toLowerCase();
	}
}

// showInTooltip
function reminderFox_compareColumnReminder1LessThanShowInTooltip( reminder1, reminder2 ) {	
	if ( reminder1.showInTooltip == false && reminder2.showInTooltip == true ) {
		return false
	}
	if ( reminder1.showInTooltip == true && reminder2.showInTooltip == false ) {
		return true;
	}
	else {
		return reminder1.originalIndex < reminder2.originalIndex;
	}
}

// notes
function reminderFox_compareColumnReminder1LessThanNotes( reminder1, reminder2 ) {	
	if ( reminder1.notes == null && reminder2.notes != null ) {
		return false
	}
	if ( reminder1.notes != null && reminder2.notes == null ) {
		return true;
	}
	else {
		return reminder1.originalIndex < reminder2.originalIndex;
	}
}

// ruc
function reminderFox_compareColumnReminder1LessThanRUC( reminder1, reminder2 ) {	
 if ( reminder1.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED &&
		( reminder2.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_TO_BE_MARKED || 
		  reminder2.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_NONE ) ) {
		return true;
	}
	else if ( reminder1.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_TO_BE_MARKED &&
		  reminder2.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_NONE  ) {
		return true;
	}	
	else if ( reminder1.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_TO_BE_MARKED &&
		  reminder2.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED  ) {
		return false;
	}	
	else if ( reminder1.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_NONE &&
		( reminder2.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_TO_BE_MARKED || 
		  reminder2.remindUntilCompleted == REMINDERFOX_REMIND_UNTIL_COMPLETE_MARKED ) ) {
		return false;
	}	
	else {
		return reminder1.originalIndex < reminder2.originalIndex;
	}
}

// mail
function reminderFox_compareColumnReminder1LessThanMail( reminder1, reminder2 ) {	
	if ( reminder1.messageID == null && reminder2.messageID != null ) {
		return false
	}
	if ( reminder1.messageID != null && reminder2.messageID == null ) {
		return true;
	}
	else {
		return reminder1.originalIndex < reminder2.originalIndex;
	}
}

// alarm
function reminderFox_compareColumnReminder1LessThanAlarm( reminder1, reminder2 ) {	
	if ( reminder1.alarm == null && reminder2.alarm != null ) {
		return false
	}
	if ( reminder1.alarm != null && reminder2.alarm == null ) {
		return true;
	}
	else {
		return reminder1.originalIndex < reminder2.originalIndex;
	}
}

// time
function reminderFox_compareColumnReminder1LessThanTime( reminder1, reminder2 ) {	
	if ( reminder1.allDayEvent == null && reminder2.allDayEvent != null ) {
		return true
	}
	if ( reminder1.allDayEvent != null && reminder2.allDayEvent == null ) {
		return false;
	}
	if ( reminder1.date == null && reminder2.date != null ) {
		return false
	}
	if ( reminder1.date != null && reminder2.date == null ) {
		return true
	}
	
	if ( reminder1.date != null && reminder2.date != null ) {		
		if ( reminder1.date.getHours() < reminder2.date.getHours() ) {
			return true;
		}
		else if ( reminder1.date.getHours() > reminder2.date.getHours() ) {
			return false;
		}		
		else {
			if ( reminder1.date.getMinutes() < reminder2.date.getMinutes() ) {
				return true;
			}
			else if ( reminder1.date.getMinutes() > reminder2.date.getMinutes() ) {
				return false;
			}		
			else { 
				// same time
				return reminder1.originalIndex < reminder2.originalIndex;
			}
		}
	}	
	else {
		return reminder1.originalIndex < reminder2.originalIndex;
	}	
}

function reminderFox_compareColumnReminder1LessThanRepeat( reminder1, reminder2 ) {	
		// yearly/monthly/weekly/daily/none -->		
		if ( reminder1.recurrence.type  == reminder2.recurrence.type ) {
			return reminder1.originalIndex < reminder2.originalIndex;
		}
				
		if ( reminder1.recurrence.type  == REMINDER_RECURRENCE_ONETIME ) {
			return false;
		}
		else if ( reminder2.recurrence.type  == REMINDER_RECURRENCE_ONETIME ) {
			return true;
		}
		else if ( reminder1.recurrence.type  == REMINDER_RECURRENCE_YEARLY ) { 			
				return true;
		}
		else if ( reminder2.recurrence.type  == REMINDER_RECURRENCE_YEARLY ) { 			
				return false;
		}
		else if ( reminder1.recurrence.type  == REMINDER_RECURRENCE_YEARLY_DAY ) {
			if (  reminder2.recurrence.type !=   REMINDER_RECURRENCE_YEARLY_DAY && 
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_YEARLY ) {
				return true;
			}
		}	
		else if ( reminder2.recurrence.type  == REMINDER_RECURRENCE_YEARLY_DAY ) {
			if (  reminder1.recurrence.type !=   REMINDER_RECURRENCE_YEARLY_DAY && 
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_YEARLY ) {
				return false;
			}
		}			
		else if ( reminder1.recurrence.type  == REMINDER_RECURRENCE_MONTHLY_DATE ) {
			if (  reminder2.recurrence.type !=   REMINDER_RECURRENCE_YEARLY_DAY && 
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_YEARLY && 
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DATE) {
				return true;
			}
		}			
		else if ( reminder2.recurrence.type  == REMINDER_RECURRENCE_MONTHLY_DATE ) {
			if (  reminder1.recurrence.type !=   REMINDER_RECURRENCE_YEARLY_DAY && 
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_YEARLY && 
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DATE) {
				return false;
			}
		}		
		else if ( reminder1.recurrence.type  == REMINDER_RECURRENCE_MONTHLY_DAY ) {
			if (  reminder2.recurrence.type !=   REMINDER_RECURRENCE_YEARLY_DAY && 
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_YEARLY && 
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DATE &&
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DAY) {
				return true;
			}
		}		
		else if ( reminder2.recurrence.type  == REMINDER_RECURRENCE_MONTHLY_DAY ) {
			if (  reminder1.recurrence.type !=   REMINDER_RECURRENCE_YEARLY_DAY && 
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_YEARLY && 
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DATE &&
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DAY) {
				return false;
			}
		}			
		else if ( reminder1.recurrence.type  == REMINDER_RECURRENCE_WEEKLY ) {
			if (  reminder2.recurrence.type !=   REMINDER_RECURRENCE_YEARLY_DAY && 
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_YEARLY && 
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DATE &&
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DAY &&
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_WEEKLY ) {
				return true;
			}
		}	
		else if ( reminder2.recurrence.type  == REMINDER_RECURRENCE_WEEKLY ) {
			if (  reminder1.recurrence.type !=   REMINDER_RECURRENCE_YEARLY_DAY && 
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_YEARLY && 
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DATE &&
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DAY &&
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_WEEKLY ) {
				return false;
			}
		}						
		else if ( reminder1.recurrence.type  == REMINDER_RECURRENCE_DAILY ) {
			if (  reminder2.recurrence.type !=   REMINDER_RECURRENCE_YEARLY_DAY && 
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_YEARLY && 
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DATE &&
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DAY &&
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_WEEKLY &&
					reminder2.recurrence.type !=   REMINDER_RECURRENCE_DAILY   ) {
				return true;
			}
		}		
		else if ( reminder2.recurrence.type  == REMINDER_RECURRENCE_DAILY ) {
			if (  reminder1.recurrence.type !=   REMINDER_RECURRENCE_YEARLY_DAY && 
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_YEARLY && 
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DATE &&
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_MONTHLY_DAY &&
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_WEEKLY &&
					reminder1.recurrence.type !=   REMINDER_RECURRENCE_DAILY   ) {
				return false;
			}
		}						
	
		return reminder1.originalIndex < reminder2.originalIndex;
}

function reminderFox_compareColumnReminder1LessThan( reminder1, reminder2, column  ) {
	// todos
	if ( column == "todoDateColLabel") {
		return reminderFox_compareColumnReminder1LessThanDate( reminder1, reminder2 );
	}
	else if ( column == "todoEndDateColLabel") {
		return reminderFox_compareColumnReminder1LessThanReminderEndDate( reminder1, reminder2 );
	}
	else if ( column == "todoDescColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanSummary( reminder1, reminder2 );
	}
	else if ( column == "todoDateCompleted" ) {
		return reminderFox_compareColumnReminder1LessThanCompletedDate( reminder1, reminder2 );
	}
	else if ( column == "todoCompleteColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanCompletedDate( reminder1, reminder2 );
	}
	else if ( column == "todoShowInTooltip" ) {
		return reminderFox_compareColumnReminder1LessThanShowInTooltip( reminder1, reminder2 );
	}
	else if ( column == "todoTimeColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanTime( reminder1, reminder2 );
	}
	else if ( column == "todoAlarmColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanAlarm( reminder1, reminder2 );
	}
	else if ( column == "todoNotesColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanNotes( reminder1, reminder2 );
	}
	else if ( column == "todoMailColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanMail( reminder1, reminder2 );
	}
	else if ( column == "todocatColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanCategory( reminder1, reminder2 );
	}	
	
	
	// reminders

	else if ( column == "descColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanSummary( reminder1, reminder2 );
	}
	else if ( column == "dateColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanDate( reminder1, reminder2 );
	}
	else if ( column == "endDateColLabel") {
		return reminderFox_compareColumnReminder1LessThanReminderEndDate( reminder1, reminder2 );
	}
	else if ( column == "timeColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanTime( reminder1, reminder2 );
	}
	else if ( column == "dateCompleted" ) {
		return reminderFox_compareColumnReminder1LessThanReminderCompletedDate( reminder1, reminder2 );
	}
	else if ( column == "repeatColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanRepeat( reminder1, reminder2 );
	}
	else if ( column == "CompleteColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanReminderCompletedDate( reminder1, reminder2 );
	}
	else if ( column == "remindUntilCompletedColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanRUC( reminder1, reminder2 );
	}
	else if ( column == "notesColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanNotes( reminder1, reminder2 );
	}
	else if ( column == "alarmColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanAlarm( reminder1, reminder2 );
	}
	else if ( column == "mailColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanMail( reminder1, reminder2 );
	}
	else if ( column == "catColLabel" ) {
		return reminderFox_compareColumnReminder1LessThanCategory( reminder1, reminder2 );
	}	
	else {	
		return false;
	}
}

function reminderFox_sortPartitionQuickAlarm(array, begin, end, pivot, sortDir)
{
	var piv=array[pivot];
	reminderFox_sortArraySwap(array, pivot, end-1);
	var store=begin;
	var ix;
	for(ix=begin; ix<end-1; ++ix) {
		var lessThan = 	array[ix].alarmTime < piv.alarmTime;
		if ( sortDir == 1 ) {
			lessThan = !lessThan;
		}
		
		if ( lessThan) {
			reminderFox_sortArraySwap( array, store, ix );
			++store;
		}
	}
	reminderFox_sortArraySwap( array, end-1, store);

	return store;
}



function reminderFox_qsortQuickArray(array, begin, end, sortDir)
{
	if(end-1>begin) {
		var pivot=begin+Math.floor(Math.random()*(end-begin));

		pivot=reminderFox_sortPartitionQuickAlarm(array, begin, end, pivot, sortDir);

		reminderFox_qsortQuickArray(array, begin, pivot, sortDir);
		reminderFox_qsortQuickArray(array, pivot+1, end, sortDir);
	}
}
// quicksort
function reminderFox_quick_sort_QuickArray(array, sortDir)
{
	reminderFox_qsortQuickArray(array, 0, array.length, sortDir );
}







function reminderFox_sortPartition(array, begin, end, pivot, column, sortDir)
{
	var piv=array[pivot];
	reminderFox_sortArraySwap(array, pivot, end-1);
	var store=begin;
	var ix;
	for(ix=begin; ix<end-1; ++ix) {
		var lessThan = reminderFox_compareColumnReminder1LessThan( array[ix], piv, column );
		if ( sortDir ==REMINDER_FOX_SORT_DIRECTION_DESCENDING ) {
			lessThan = !lessThan;
		}
		
		if ( lessThan) {
			reminderFox_sortArraySwap( array, store, ix );
			++store;
		}
	}
	reminderFox_sortArraySwap( array, end-1, store);

	return store;
}



function reminderFox_qsort(array, begin, end, column, sortDir)
{
	if(end-1>begin) {
		var pivot=begin+Math.floor(Math.random()*(end-begin));

		pivot=reminderFox_sortPartition(array, begin, end, pivot, column, sortDir);

		reminderFox_qsort(array, begin, pivot, column, sortDir);
		reminderFox_qsort(array, pivot+1, end, column, sortDir);
	}
}
// quicksort
function reminderFox_quick_sort(array, column, sortDir)
{
	reminderFox_qsort(array, 0, array.length, column, sortDir );
}


function reminderFox_addReminderHeadlessly( newReminderToBeAdded, replaceEventIfAlreadyExists, isEdit, isTodo) {  
	if ( isEdit == null ) { 
		isEdit = false;
	}

	var newOptions = { reminder: newReminderToBeAdded, editing:  isEdit,  addEvent: false, listToBeAddedTo: "",
	     isTodo: isTodo };    //gW_AddEvent via Clipboard  2010-08-27
	window.openDialog("chrome://reminderfox/content/editing/reminderEventDialog.xul",
			"reminderOptionsDialog", "chrome,resizable,modal", newOptions );

	if ( newOptions.addEvent ) {
		newReminderToBeAdded = newOptions.reminder;		
		
		var currentDate = new Date();
		if ( newReminderToBeAdded.alarm != null ) {
			newReminderToBeAdded.alarmLastAcknowledge = currentDate.getTime();
		}
		newReminderToBeAdded.lastModified = reminderFox_getDateAsString(currentDate );
		
		// add reminder in sorted order...
		// add to edit reminder dialog if it is open
	   var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
	   var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
	   var topWindow = windowManagerInterface.getMostRecentWindow("window:reminderFoxEdit");	 
	   if (topWindow) {
	   		if ( newOptions.listToBeAddedTo == REMINDER_FOX_DEFAULT_REMINDERS_CATEGORY ) { // add to reminders	   	
		   		var newDate = oeDatePicker.gSelectedDate;
				if ( newDate == null ) {
					newDate = new Date();
				}	
				var originalYear = newDate.getFullYear();
		   		// if adding a new reminder in a different year, first set the list/calendar to the new year
				// before adding the reminder
				if ( originalYear != newReminderToBeAdded.date.getFullYear() ) {
				   	topWindow.oeDatePicker.gSelectedDate = newReminderToBeAdded.date;
					topWindow.repopulateListForYear( originalYear, newReminderToBeAdded.date.getFullYear() );
				}
		   	
		   		topWindow.focus();
		   		
		   		// remove this event if it already exists, so it will be replaced 
		   		if ( replaceEventIfAlreadyExists ) {
					topWindow.removeListItemsForReminder(newReminderToBeAdded);  // remove from UI list
					
					var reminders = topWindow.reminderFox_getReminderEvents();	 // remove from model list
					for( var i = 0; i < reminders.length; i++) {
						if ( reminders[i].id == newReminderToBeAdded.id ) {
							topWindow.reminderFox_removeElement(reminders, i);
							break;
						}
					}
				}
		   			   		
		   		var reminders = topWindow.reminderFox_getReminderEvents();	
				var sortedIndex = topWindow.reminderFox_getSortedIndexOfNewReminder( reminders, newReminderToBeAdded, false );
				topWindow.reminderFox_insertIntoArray( reminders, newReminderToBeAdded, sortedIndex );
		   	
				topWindow.createListItem(newReminderToBeAdded);
				topWindow.oeDatePicker.onpopupshowing(newReminderToBeAdded.date);			
				topWindow.modifiedReminders();	
	  		 }
	  		 else {
	  		 	// add todo in sorted order...
	  		 	topWindow.focus();
	  		 	
				var reminderFoxTodosArrayArg =  	topWindow.reminderFox_getReminderTodos();
				var todos = reminderFoxTodosArrayArg[newOptions.listToBeAddedTo];  // listname == get list from list name...	
				if ( todos == null ) {
					todos = new Array();
					reminderFoxTodosArrayArg[newOptions.listToBeAddedTo] = todos;				
				}		
				if( replaceEventIfAlreadyExists ) {
					// remove from model list					
					for( var i = 0; i < todos.length; i++) {
						if ( todos[i].id == newReminderToBeAdded.id ) {
							reminderFox_removeElement(todos, i);
							break;
						}
					}
				}
								
				var sortedIndex = topWindow.reminderFox_getSortedIndexOfNewTodo(todos,  newReminderToBeAdded );		
				topWindow.reminderFox_insertIntoArray( todos, newReminderToBeAdded, sortedIndex );
				
				// UI
				topWindow.createTodoListItem(newReminderToBeAdded, true, new Date(), true);				
				topWindow.sortTodoIfNeccessary( newReminderToBeAdded.id);
				topWindow.modifiedReminders();		  		 	
	  		 }
		}		
		else {			
			if ( newOptions.listToBeAddedTo == REMINDER_FOX_DEFAULT_REMINDERS_CATEGORY ) { // add to reminders
				// remove this event if it already exists, so it will be replaced 
				var reminders = reminderFox_getReminderEvents();	
				if ( replaceEventIfAlreadyExists ) {
					// remove from model list					
					for( var i = 0; i < reminders.length; i++) {
						if ( reminders[i].id == newReminderToBeAdded.id ) {
							reminderFox_removeElement(reminders, i);
							break;
						}
					}
				}
				
				// add reminder headlessly
				var sortedIndex = reminderFox_getSortedIndexOfNewReminder( reminders, newReminderToBeAdded, false );
				reminderFox_insertIntoArray( reminders, newReminderToBeAdded, sortedIndex );			
			}
			else {
				// add to todo list

				// add todo in sorted order...
				var reminderFoxTodosArrayArg =  reminderFox_getReminderTodos();
				var todos = reminderFoxTodosArrayArg[newOptions.listToBeAddedTo];  // listname == get list from list name...
				if ( todos == null ) {
					todos = new Array();
					reminderFoxTodosArrayArg[newOptions.listToBeAddedTo] = todos;
				}		
				if( replaceEventIfAlreadyExists ) {
					// remove from model list					
					for( var i = 0; i < todos.length; i++) {
						if ( todos[i].id == newReminderToBeAdded.id ) {
							reminderFox_removeElement(todos, i);
							break;
						}
					}
				}
								
				var sortedIndex = reminderFox_getSortedIndexOfNewTodo(todos,  newReminderToBeAdded );
				reminderFox_insertIntoArray( todos, newReminderToBeAdded, sortedIndex );
			}							
		}
		reminderFox_processRecentReminders();
		reminderFox_writeOutRemindersAndTodos(false);
		reminderFox_syncWrittenChangesToRemote(	);
		try {
			// update all of the browsers
			var windowEnumerator =  reminderFox_getWindowEnumerator();
			while (windowEnumerator.hasMoreElements()) {
				var currentWindow = windowEnumerator.getNext();		
				currentWindow.reminderFoxEvents = reminderFoxEvents;
				currentWindow.reminderFoxTodosArray  = reminderFoxTodosArray;

				currentWindow.reminderFox_updateRemindersInWindow();			
				currentWindow.reminderFox_clearRemindersAndTodos();
			}
		}
		catch(e) {
		}				
		
	}
	
	gRmFx_LastEvent = newReminderToBeAdded;
	return newOptions.addEvent;
}




function reminderFox_editEventHeadlessly( eventId, newReminderToBeAdded, isReminder ) {  
   var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
   var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
   var topWindow = windowManagerInterface.getMostRecentWindow("window:reminderFoxEdit");
 
   if (topWindow) {
    	 topWindow.focus();
    	if ( isReminder == true ) {	 
			topWindow.selectReminderById( eventId);
			topWindow.editReminder();
    	}
    	else { 
			var reminderFoxTodosArrayArg =  reminderFox_getReminderTodos();
			for ( var n in reminderFoxTodosArrayArg ) {
				var reminderTodos = reminderFoxTodosArrayArg[n];
				for (  var i = 0; i < reminderTodos.length; i++ ) {		
					if ( reminderTodos[i].id == eventId ) {
						topWindow.selectTodoById(n, eventId	);
						topWindow.editTodo();
						break;
					}
				}
			}
		}    		
   }
   else {
	var newOptions = null;
	var added = false;
	var addedEvent = null;
	if ( isReminder ) {
		var activeReminders = reminderFox_getReminderEvents();
		for ( var i = 0; i < activeReminders.length; i++ ) {
			if (activeReminders[i].id == eventId) {
				newReminderToBeAdded = activeReminders[i];
				break;
			}
		}
		
		newOptions = { reminder: newReminderToBeAdded, editing:  true,  addReminder: false, showMail: false,  readonly: false };
		window.openDialog("chrome://reminderfox/content/editing/reminderOptionsDialog.xul",
			"window:reminderFoxReminderOptionsDialog", "chrome,resizable,modal", newOptions);
		if ( newOptions.addReminder ) { 
			added = true;
			newReminderToBeAdded = newOptions.reminder;		
		}
	}
	else {
		var listToBeAddedTo = null;
		if ( newReminderToBeAdded == null ) {
			var reminderFoxTodosArrayArg =  reminderFox_getReminderTodos();
			for ( var n in reminderFoxTodosArrayArg ) {
				var reminderTodos = reminderFoxTodosArrayArg[n];
				for (  var i = 0; i < reminderTodos.length; i++ ) {		
					if ( reminderTodos[i].id == eventId ) {
						newReminderToBeAdded = reminderTodos[i];
						listToBeAddedTo = n;
						break;
					}
				}
			}
		}
		
		
		newOptions = { todo: newReminderToBeAdded, editing:  true,  addTodo: false, showMail: false };
		window.openDialog("chrome://reminderfox/content/editing/todoOptionsDialog.xul",
				"todoOptionsDialog", "chrome,resizable,modal", newOptions );
		if ( newOptions.addTodo ) { 
			added = true;
			newReminderToBeAdded = newOptions.todo;		
		}
	}	

	if ( added ) {
		var currentDate = new Date();
		if ( newReminderToBeAdded.alarm != null ) {
			newReminderToBeAdded.alarmLastAcknowledge = currentDate.getTime();  // <-- acknowledged here which can update the reminder; then if you don't SNOOZE but click X, it would never snooze again.  That may be ok...
		}
		newReminderToBeAdded.lastModified = reminderFox_getDateAsString(currentDate );
		
			if ( isReminder ) { // add to reminders
				// remove this event if it already exists, so it will be replaced 
				var reminders = reminderFox_getReminderEvents();	
					// remove from model list					
					for( var i = 0; i < reminders.length; i++) {
						if ( reminders[i].id == newReminderToBeAdded.id ) {
							reminderFox_removeElement(reminders, i);
							break;
						}
					}
				
				// add reminder headlessly
				var sortedIndex = reminderFox_getSortedIndexOfNewReminder( reminders, newReminderToBeAdded, false );
				reminderFox_insertIntoArray( reminders, newReminderToBeAdded, sortedIndex );			
			}
			else {
				// add to todo list

				// add todo in sorted order...
				var reminderFoxTodosArrayArg =  reminderFox_getReminderTodos();
				
				// get the list this belongs to
				if ( listToBeAddedTo == null ) { 
					for ( var n in reminderFoxTodosArrayArg ) {
						var reminderTodos = reminderFoxTodosArrayArg[n];
						for (  var i = 0; i < reminderTodos.length; i++ ) {		
							if ( reminderTodos[i].id == eventId ) {
								listToBeAddedTo = n;
								break;
							}
						}
					}
				}
				var todos = reminderFoxTodosArrayArg[listToBeAddedTo];  
				if ( todos == null ) {
					todos = new Array();
					reminderFoxTodosArrayArg[listToBeAddedTo] = todos;
				}		
				
					// remove from model list					
					for( var i = 0; i < todos.length; i++) {
						if ( todos[i].id == newReminderToBeAdded.id ) {
							reminderFox_removeElement(todos, i);
							break;
						}
					}
								
				var sortedIndex = reminderFox_getSortedIndexOfNewTodo(todos,  newReminderToBeAdded );
				reminderFox_insertIntoArray( todos, newReminderToBeAdded, sortedIndex );
			}			
			
			reminderFox_processRecentReminders();
			reminderFox_writeOutRemindersAndTodos(false);
			reminderFox_syncWrittenChangesToRemote(	);
			try {
				// update all of the browsers
				var windowEnumerator =  reminderFox_getWindowEnumerator();
				while (windowEnumerator.hasMoreElements()) {
					var currentWindow = windowEnumerator.getNext();		
					currentWindow.reminderFoxEvents = reminderFoxEvents;
					currentWindow.reminderFoxTodosArray  = reminderFoxTodosArray;
	
					currentWindow.reminderFox_updateRemindersInWindow();			
					currentWindow.reminderFox_clearRemindersAndTodos();
				}
			}
			catch(e) {
			}			
		}
	}
	
	return newReminderToBeAdded;
}



function reminderFox_firstStart() {
	//  If this is the very first ReminderFox start (no existing 'reminder.ics' file available),
    //  we construct a 'Welcome ReminderFox' reminder.
    var rmStoreFile =   reminderFox_getReminderStoreFile();
    if ( rmStoreFile == null || !rmStoreFile.exists() ) {
    	var todaysDate = new Date();
		var reminderId =reminderFox_generateUniqueReminderId( todaysDate );
    	var newReminderToBeAdded = new ReminderFoxEvent( reminderId, todaysDate, reminderFox_getBundle().getString("rf.welcome.header") );  
    	newReminderToBeAdded.notes =  reminderFox_getBundle().getString("rf.welcome.notes");
    	newReminderToBeAdded.url =  reminderFox_getBundle().getString("rf.faqURL");
    	
    	var reminders = reminderFox_getReminderEvents();	
		reminderFox_insertIntoArray( reminders, newReminderToBeAdded, 0 );
		reminderFox_writeOutRemindersAndTodos(false);
		
		// add default views
		rmFx_migrate_defaultView('Set');
		
	}
}


function reminderFox_mail_getTimeString( date ) {
	var timeString = null;
	try {
		var hours = date.getHours();
		var AMorPM;
			
		var use24HourTime;
		try {
			use24HourTime = reminderFox_prefs.getBoolPref(REMINDER_FOX_PREF + "." + REMINDER_FOX_USE_24_HOUR_TIME);
		} catch(e) {
		}				
		if (  use24HourTime ) {
			AMorPM = "";
			if ( hours < 10 ) {
				hours = "0" + hours;
			}
		}
		else {
			AMorPM  =reminderFox_getBundle().getString("rf.add.time.PM");
			if ( AMorPM != "" ) {
				if ( hours < 12 ) {
					AMorPM = reminderFox_getBundle().getString("rf.add.time.AM");
				}
				if ( hours == 0 ) {
					hours = 12;
				}
				if ( hours >= 13 ) {
					hours = hours -12;
				}	
			}	
		}
		var minutes = date.getMinutes();
		if ( minutes < 10 ) {
			minutes = "0" + minutes;
		}
						
		timeString = hours + reminderFox_getBundle().getString("rf.add.time.delimiter") + minutes;
		if ( AMorPM != "" ) {
			timeString = timeString + " " + AMorPM;		
		}
	}
	catch ( e ) { 
	}
	
	return timeString;
}

function reminderFox_convertReminderToTodo(currentReminder) {
	var newTodo = new ReminderFoxTodo( currentReminder.id, currentReminder.summary, currentReminder.date);			
	newTodo.notes = currentReminder.notes;
	newTodo.priority = currentReminder.priority;
	newTodo.messageID = currentReminder.messageID;
	newTodo.completedDate = currentReminder.completedDate;
	newTodo.endDate = currentReminder.endDate;
	newTodo.durationTime = currentReminder.durationTime;
	newTodo.allDayEvent = currentReminder.allDayEvent;	
	newTodo.alarm = currentReminder.alarm;		
	newTodo.alarmLastAcknowledge = currentReminder.alarmLastAcknowledge;		
	newTodo.snoozeTime = currentReminder.snoozeTime;
	newTodo.recurrence = currentReminder.recurrence;  
	newTodo.extraInfo = currentReminder.extraInfo;
	newTodo.categories = currentReminder.categories;
	newTodo.location = currentReminder.location;
	newTodo.url = currentReminder.url;
	return newTodo;
}

function reminderFox_convertTodoToReminder(currentTodo) {
	var newReminder = new ReminderFoxEvent( currentTodo.id, currentTodo.date, currentTodo.summary );			
	newReminder.notes = currentTodo.notes;
	newReminder.priority = currentTodo.priority;
	newReminder.messageID = currentTodo.messageID;
	newReminder.completedDate = currentTodo.completedDate;
	newReminder.endDate = currentTodo.endDate;
	newReminder.durationTime = currentTodo.durationTime;
	newReminder.allDayEvent = currentTodo.allDayEvent;	
	newReminder.alarm = currentTodo.alarm;		
	newReminder.alarmLastAcknowledge = currentTodo.alarmLastAcknowledge;		
	newReminder.snoozeTime = currentTodo.snoozeTime;
	newReminder.recurrence =	currentTodo.recurrence;  
	newReminder.extraInfo = currentTodo.extraInfo;
	newReminder.categories = currentTodo.categories;
	newReminder.location = currentTodo.location;
	newReminder.url = currentTodo.url;
	return newReminder;
}


//function reminderFox_getAllReminderEvents() {
//	var allReminders= new Array();
//	var reminderFoxEventsArrayArg = reminderFox_getReminderEvents();  // iterate over all reminders
//  	for ( var n in reminderFoxEventsArrayArg ) {
//		var reminderFoxEvents = reminderFoxEventsArrayArg[n];
//	  	for (var i = 0; i < reminderFoxEvents.length; i++ ) {
//	  		allReminders[allReminders.length] = reminderFoxEvents[i];			
//	  	}
//  	} 
//  	return allReminders; 
//}

function reminderFox_getAllReminderTodos() {
	var allTodos = new Array();
	var reminderFoxTodosArrayArg = reminderFox_getReminderTodos();  // iterate over all reminders
  	for ( var n in reminderFoxTodosArrayArg ) {
		var reminderFoxTodos = reminderFoxTodosArrayArg[n];
	  	for ( var i = 0; i < reminderFoxTodos.length; i++ ) {
	  		allTodos[allTodos.length] = reminderFoxTodos[i];			
	  	}
  	} 
  	return allTodos;
}

function reminderFox_getValidCustomTodoLists() {
	var todoListsRet = new Array();
	var todoLists = reminderFox_getPreferenceValue( REMINDER_FOX_TODO_LISTS );
 	if ( todoLists != null && todoLists.length > 0) { 	
 		var subscriptions = reminderFox_getSubscriptions();		
 		var todoListsArray = todoLists.split(",");
		for ( var i = 0; i < todoListsArray.length; i++ )  { 		
			var listItem = 	todoListsArray[i];
			if ( subscriptions[listItem] == null ) {
				todoListsRet[todoListsRet.length] = listItem;
			}
		}
 	}
 	return todoListsRet;
}


function reminderFox_getAllCustomTodoLists() {
	var todoListsRet = new Array();
	var todoLists = reminderFox_getPreferenceValue( REMINDER_FOX_TODO_LISTS );
 	if ( todoLists != null && todoLists.length > 0) { 	 		
 		var todoListsArray = todoLists.split(",");
		for ( var i = 0; i < todoListsArray.length; i++ )  { 		
			var listItem = 	todoListsArray[i];			
			todoListsRet[todoListsRet.length] =listItem;			
		}
 	}
 	return todoListsRet;
}

function reminderFox_getSubscriptions() {
	
	var subscriptionsArray = {};
	var todoLists = reminderFox_getPreferenceValue( REMINDER_FOX_SUBSCRIPTIONS );
 	if ( todoLists != null && todoLists.length > 0) { 	
 		var todoListsArray = todoLists.split(",");
		for ( var i = 0; i < todoListsArray.length; i++ )  { 		
			var listItem = 	todoListsArray[i];
			var subscription = listItem.indexOf( "=");
			var listName = listItem.substring( 0, subscription );
			var subscriptionURL = listItem.substring( subscription + 1);			
			subscriptionsArray[listName] = subscriptionURL;
		}
 	}
 	return subscriptionsArray;
}

function reminderFox_writeSubscriptions( subscriptions ) {
	var subscriptionsStr = "";
	for ( var listName in subscriptions ) {
		var subUrl = subscriptions[listName];
		if ( subUrl != null && subUrl.length > 0 ) {
			if ( subscriptionsStr.length > 0 ) {
				subscriptionsStr = subscriptionsStr + "," + listName + "=" + subUrl;
			}
			else {
				subscriptionsStr = listName + "=" + subUrl;
			}
		}
	}
	reminderFox_setUnicodePref( REMINDER_FOX_SUBSCRIPTIONS, subscriptionsStr);		
	
}

function reminderFox_findParentById( node, name1, name2 ) {
	var parentNode = node;
    while ( parentNode != null ) {
    	if ( parentNode.id == name1 || parentNode.id == name2 ) {
    		return parentNode;
    	}
    	
    	parentNode = parentNode.parentNode;
    }
    return parentNode;
}

function reminderFox_adjustDateForTimeZones( eventDateString, fullDateString, reminderDate ) {
	// if event is stored in UTC time (20051208T224616Z), then take into account UTC offset for the 
	// current time
	if ( eventDateString.length > 15 && eventDateString.charAt(15) == "Z" ) {  		
		var tzOffset = new Date(
			reminderDate.getFullYear(),reminderDate.getMonth(),
			reminderDate.getDate()).getTimezoneOffset();
		reminderDate.setMinutes( reminderDate.getMinutes() - tzOffset );						
	}
	else {
		// if date contains a Timezone in its specification, handle it if we know the timezone id.
		// DTSTART;TZID=US/Pacific:20071007T100000
		// logic: get target timezone: Pacific  (-8)
		// 			get my current timezone offset:  myOffset (-5)
		// 			tzOffset = myOffset -targetTimezoneOffset (-5 - -8 = +3)
		var timezoneIndex = fullDateString.indexOf( ";TZID=" );
		if ( timezoneIndex != -1 ) {
			var endIndex = fullDateString.indexOf(':', timezoneIndex );
			var timezone = fullDateString.substring( timezoneIndex + ";TZID=".length, endIndex );
			timezone = reminderFox_trim( timezone.toUpperCase() );
			var offset = reminderFox_timezones[timezone];
			if ( offset == null ) {
				// in minutes
				if ( timezone == "US/EASTERN" || timezone == "US-EASTERN" ) {
					offset = 5;
				}
				else if ( timezone == "US/CENTRAL" || timezone == "US-CENTRAL" ) {
					offset = 6;
				}
				else if ( timezone == "US/MOUNTAIN" || timezone == "US-MOUNTAIN") {
					offset = 7;
				}
				else if ( timezone == "US/PACIFIC" || timezone == "US-PACIFIC") {
					offset = 8;
				}
				else if ( timezone == "US/ALASKA" || timezone == "US-ALASKA") {
					offset = 9;
				}
				else if ( timezone == "US/HAWAII" || timezone == "US-HAWAII") {
					offset = 11;
				}
				else {
					// if we don't know what this timezone is, do nothing
					offset = 0;
					reminderFox_timezones[timezone] = offset;
					return;
				}
				
				/*
				 * Beginning in 2007, most of the United States begins Daylight Saving Time at 2:00 a.m. on the second Sunday in March and reverts to standard time on the first Sunday in November. 
				 */
				 var startDSTDate = new Date(2007, 2, 11 );
				 var endDSTDate = new Date( 2007, 10, 4 );
				 
				 var startDSTDay = startDSTDate.getDay();
				 var weekNumber = reminderFox_getWeekNumber( startDSTDate );
				
				var thisMonthsDate = new Date();
				thisMonthsDate.setDate(1); // set to start of the month
				thisMonthsDate.setMonth(2);
				//var reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( startDSTDate, startDSTDay, weekNumber );
				var reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( thisMonthsDate, startDSTDay, weekNumber ); 
				var startDate = new Date( thisMonthsDate.getFullYear(), startDSTDate.getMonth(), reminderWeekDateThisMonth );
				
				thisMonthsDate.setMonth(10);
				var endDSTDay = endDSTDate.getDay();
				 weekNumber = reminderFox_getWeekNumber( endDSTDate );
				reminderWeekDateThisMonth = reminderFox_getDateForSpecifiedWeekNumber( thisMonthsDate, endDSTDay, weekNumber );
				var endDate = new Date( thisMonthsDate.getFullYear(), endDSTDate.getMonth(), reminderWeekDateThisMonth );
				
				var todaysDate = new Date();
				if (  reminderFox_compareDates( todaysDate, startDate ) >= 0 &&
				 reminderFox_compareDates( todaysDate, endDate ) == -1) {
					// we are in DST; subtract one hour 
					offset--;
				}
				
				offset = offset*60;  // convert to minutes
				reminderFox_timezones[timezone] = offset * -1;   // timezone is negative for US (-0500)
			}
			if ( offset == 0 ) {
				return;
			}
			var tzOffset = new Date().getTimezoneOffset(); 
			var diff = tzOffset + offset;
			reminderDate.setMinutes( reminderDate.getMinutes() - diff );		
		}			
	}
}


/////////////////////////// Core Utilities /////////////////////////////////////

function rmFxCore (){
}
// gW 2008-10-28  ... currently used with 'Options'  and 'View'

	rmFxCore.add2Textbox = function (xThis, addID, separator) {
	// -------------------------------------------------------------------------
	// gW 2008-10-28  ... currently used with 'Options'  and 'View'
	
		var element=	xThis.childNodes[xThis._lastSelectedRow]
				.childNodes[0].childNodes[0].attributes[0].value;
				
		var currentText =	document.getElementById(addID);				
		var part1 = currentText.value.substring(0,currentText.selectionStart);	
		var part2 = currentText.value.substring(currentText.selectionEnd, currentText.textLength);
		document.getElementById(addID).value = part1 +  separator +  element + " " + part2;			
	}

	rmFxCore.InfoButton = function (xThis)  {
	// ------------------------------------------------------------------------	
		var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                     .getService(Components.interfaces.nsIPromptService);
		prompts.alert(null, "ReminderFox Info", 
				(g_reminderFoxBundle.getString(xThis.attributes["textContent"].nodeValue)));
	}
	

	rmFxCore.statusSet = function (text)  {
	// -------------------------------------------------------------------------
	// Generic function to set 'RmFx Status' ... tribute to g.Tom ;-)
	
		// comment out by tfm on 10/03/2010...  if "" text was not immediately set,
		// it was causing the case where "Downloading subscribed reminders" message
		// would be displayed for 10 seconds after it had completed.  
		// So we will instead immediately set any "" text
		//if (text == "" ){ return;}
		
		var rmFx_consoleService = Components.classes["@mozilla.org/consoleservice;1"]
				.getService(Components.interfaces.nsIConsoleService);
//???	rmFx_consoleService.logStringMessage("ReminderFox: Status msg: " + text);
		if (text != null && text != "" && text.length > 0) {
			reminderFox_logMessageLevel("ReminderFox: Status msg: " + text, REMINDER_FOX_LOG_LEVEL_INFO);
		}
		
		// used with some dialogs like Views ..
		var statusTxt1 = document.getElementById("statusMsg");
		if (statusTxt1 != null) {				
			statusTxt1.setAttribute("value", text);
			statusTxt1.setAttribute("hidden", "false");
			sizeToContent();
			setTimeout(rmFxCore.statusReset,10000);
		}
		// used with ReminderFox List 'Statusline'  
      var statusTxt = document.getElementById("reminderFox-network-status");        
      if (statusTxt != null) {
         statusTxt.setAttribute("value", text); 
		 if (text != "") {
		 	setTimeout(rmFxCore.statusReset, 10000);
		 }
      }
      var statusTxt = document.getElementById("reminderFox-network-status-todo");        
      if (statusTxt != null) {
         statusTxt.setAttribute("value", text);    
         if (text != "") {
		 	setTimeout(rmFxCore.statusReset, 10000);
		 }
      }
		// used with mozApp (TB/FX..) statusbar 
		var mainStatusText = document.getElementById('statusText');
		if (mainStatusText != null) {
			text = text.replace((/\n/g)," ");
			mainStatusText.setAttribute("label", 'ReminderFox:  ' 
			+ text);
			if (text != "") {
			 	setTimeout(rmFxCore.statusReset, 10000);
			 }
		}	
}

	rmFxCore.statusReset = function ()  {
	// -------------------------------------------------------------------------
	// Generic function to reset 'RmFx Status' 
	
      var statusTxtR = document.getElementById("reminderFox-network-status");        
      if (statusTxtR != null) {statusTxtR.setAttribute("value",""); }
      
      var statusTxtT = document.getElementById("reminderFox-network-status-todo");        
      if (statusTxtT != null) {statusTxtT.setAttribute("value",""); }

		var statusTxt1 = document.getElementById("statusMsg");			
			if (statusTxt1 != null) {
				statusTxt1.setAttribute("value",""); 
				statusTxt1.setAttribute("hidden", "true");
				sizeToContent();
		}

		var mainStatusText = document.getElementById('statusText');
		if (mainStatusText != null) {
			mainStatusText.setAttribute("label", '');
		}	
}


	rmFxCore.Send2List = function () {
	// =========================================================================
 
 	var subject = " "; // Feedback / Support Request ... ";
	var body 	= "Please describe your Feedback or Support Request"
					+ " and set an appropriate 'Subject'."
					+ "\n\n ___________________________________________________"
					+ "\n ReminderFox [" + REMINDER_FOX_MIGRATED_PREF_VERSION + "]" 
					+ "\n " + navigator.userAgent;

 	var 	mailtoUrl  = "mailto:reminderfox@mozdev.org";
 			mailtoUrl += "?subject=" + encodeURIComponent(subject);
			mailtoUrl += "&body=" + encodeURIComponent(body);

	
	//reminderFox_openURL(mailtoUrl);	return;

	//-----------------					
	var ioService = Components.classes["@mozilla.org/network/io-service;1"]
                              .getService(Components.interfaces.nsIIOService);
	var uri = ioService.newURI(mailtoUrl, null, null);

	// now pass this uri to the operating system
	var extProtocolSvc =
       Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
                 .getService(Components.interfaces.nsIExternalProtocolService);
	if (extProtocolSvc)
   	extProtocolSvc.loadUrl(uri);	
   	
   return;	
	
} 

	rmFxCore.infoXR = function () {
	// --------------------------------------------------------------------------
			var info = 	rmFxCore.infoApp("name");
			info = info +  "  Version: "	+ rmFxCore.infoApp("version");
			info = info +  "  build: "		+ rmFxCore.infoApp("build") + "; ";
			info = info +  "  Platform: " + rmFxCore.infoOS();
			
			return info;
	};
	
	rmFxCore.infoApp = function (id) {
	// --------------------------------------------------------------------------
		var appId = Components.classes["@mozilla.org/xre/app-info;1"]
			.getService(Components.interfaces.nsIXULAppInfo);
		var info;

		switch (id) {
			case 'vendor': 	info= appId.vendor 	
										.replace(new RegExp(/_AT_/),"@")
										.replace(new RegExp(/_DOT_/g),".")
										.replace(new RegExp(/\(/),"<")
										.replace(new RegExp(/\)/),">"); 
								break;
					
			case 'name':		info= appId.name; 		break;
			case 'version':		info= appId.version; 	break;
			case 'build':		info= appId.appBuildID; break;
		}
		return info;
	};
	
	rmFxCore.infoOS = function () {
	// --------------------------------------------------------------------------
		var osInfo = Components.classes["@mozilla.org/xre/app-info;1"] 
			.getService(Components.interfaces.nsIXULRuntime);
		
		// OSinfo : WINNT/x86-msvc
		// OSinfo : Linux/x86-gcc3
		// OSinfo : Darwin 
		return osInfo.OS + "/" + osInfo.XPCOMABI ;
	};

        
    /**
     *   build different date/time formats used with normal mail messages                           
     */
    rmFxCore.mailDateTime = function (thisdate, format)  {
    // =========================================================================
        var sDaysOfWeek     = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
        var sMonths         = ["Jan","Feb","Mar","Apr","May","Jun",
                                    "Jul","Aug","Sep","Oct","Nov","Dec"];
        var offset          = thisdate.getTimezoneOffset();
    
        function dVal(val) { 
            if (val < 10) val = "0" + val;
            return val; 
        }
    
        if (format == "mailDate") {     //Fri, 06 Jun 2008 23:47:53 +0200
        var     s  = sDaysOfWeek[thisdate.getDay()] + ", ";
                s += thisdate.getDate()                 + " ";
                s += sMonths[thisdate.getMonth()]   + " ";
                s += thisdate.getFullYear()             + " ";
            
                s += dVal(thisdate.getHours())      + ":";
                s += dVal(thisdate.getMinutes())    + ":";
                s += dVal(thisdate.getSeconds())    + " ";
        if (offset < 0) {
            offset *= -1;
            s += "+";
        }
        else
            s += "-";
    
        s += dVal(Math.floor (offset / 60));
        s += dVal(Math.floor (offset % 60));
        }
    
        if (format == "mailHeader") {       //Fri Jun 13 20:37:33 2008
        var     s  = sDaysOfWeek[thisdate.getDay()] + " ";
                s += sMonths[thisdate.getMonth()]   + " ";
                s += thisdate.getDate()                 + " ";
            
                s += dVal(thisdate.getHours())      + ":";
                s += dVal(thisdate.getMinutes())    + ":";
                s += dVal(thisdate.getSeconds())    + " ";
    
                s += thisdate.getFullYear()             + " ";
        }
        return s;
    }

		
	// some extensions for ReminderLens
	function xrRL (){
	};
	
	xrRL.getLastDayOfMonth = function ( year, month) {
		//--------------------------------------------------------------------------
		   var pastLastDate = new Date( year, month, 32 );
		   return 32 - pastLastDate.getDate();
	};	
   
   
   